11
头图

JS-异步代码maind.png

Preface

Asynchronous means asynchronous....

This section may be a bit boring, but it is a very important concept in JavaScript and it is necessary to learn.

purpose

  • Improve development efficiency and write easy-to-maintain code

Introductory question

  • Why is the page stuck when requesting? ?
$.ajax({
  url: "www.xx.com/api",
  async: false, // true
  success: function(result) {
    console.log(result);
  },
});
  • Why is the data updated, but the DOM is not updated? ?
// 异步批量更新DOM(vue-nextTick)
// <div id="app">{{num}}</div>
new Vue({
  el: "#app",
  data: {
    num: 0,
  },
  mounted() {
    let dom = document.getElementById("app");
    while (this.num !== 100) {
      this.num++;
    }
    console.log("Vue num=" + this.num, "DOM num=" + dom.innerHTML);
    // Vue num=100,DOM num=0
    // nextTick or setTimeout
  },
});

Causes of asynchrony

Reason: Single thread (one thing at a time), the browser's JS engine is caused by single thread.

single thread means that there is only one thread responsible for interpreting and executing IavaScript code in the JS engine, so it may be called the main thread.

The so-called single thread means that only one task can be completed at a time. If there are multiple tasks, they must be queued, and the previous task is completed before the next task is executed.

Let's take a look at the thread diagram of the browser kernel:
Browser thread.jpg

Among them, the rendering thread and the JS thread are mutually exclusive .

Suppose there are two functions, one to modify and the other to delete, and operate a DOM node at the same time. If there are multiple threads, if the two threads are executed together, there will definitely be a deadlock, and there will be problems.

Why is JS designed to be single-threaded, because of the special environment of the browser.

Advantages and disadvantages of single thread:

The advantage of this model is that it is relatively simple to implement and the execution environment is relatively simple; the is that as long as one task takes a long time, the subsequent tasks must be queued, which will delay the execution of the entire program. Common browsers are not responding (fake death), often because a certain piece of Javascript code runs for a long time (such as an infinite loop), which causes the entire page to be stuck in this place and other tasks cannot be performed.

Common blockage (endless loop):

while (true) {}

JS was designed as a scripting language that runs in the browser at the beginning, so I didn't want to be so complicated, so it was designed to be single threaded, that is, can only do one thing at a time.

To solve the shortcoming of single-threaded blocking order to 160b3b690b2cdf: asynchronous.

Take instant noodles for example:

  • Synchronization: Buy instant noodles = "Boiling water (staring) = "Cooking noodles = "Eating instant noodles
  • Asynchronous: Buy instant noodles = "Boiling water (when the water is boiling, the kettle sounds-callback) = "Watch TV = "Cooking noodles (when the noodles are ready, the kettle sounds-callback) = "Watch TV = "Come on and call me = "Eat Instant noodles

Watching TV is an asynchronous operation, and the sound of the kettle is a callback function.

Asynchronous programming

Most of the code in JS is executed synchronously, only a few functions are executed asynchronously, and asynchronously executed code requires asynchronous programming.

Asynchronous code

setTimeout(() => {
  console.log("log2");
}, 0);
console.log("log1");
// ?? log1 log2

The characteristics of asynchronous code: is not executed immediately, but needs to wait and execute at a certain point in the future.

synchronization code asynchronous code
<script> codeNetwork request (Ajax)
I/O operationsTimer (setTimeout, setInterval)
Rendering operationPromise(then)
async/await

Callback

The most common way to write asynchronous code is to use callback functions.

  • HTTP network request (request is successful, execute xx operation after recognition)
  • DOM event binding mechanism (user executes xx operation after triggering the event)
  • Timer (setTimeout, setInterval) (execute xx operation after reaching the set time)
// 注意到click方法中是一个函数而不是一个变量
// 它就是回调函数
$("#btn_1").click(function() {
  alert("Btn 1 Clicked");
});
// 或者
function click() {
  // 它就是回调函数
  alert("Btn 1 Clicked");
}
$("#btn_1").click(click);

The shortcomings of the callback function are also obvious, and it is easy to produce callback hell:
callbackhell.png

Three ways of asynchronous programming

  • callback
function getOneNews() {
  $.ajax({
    url: topicsUrl,
    success: function(res) {
      let id = res.data[0].id;
      $.ajax({
        url: topicOneUrl + id,
        success: function(ress) {
          console.log(ress);
          render(ress.data);
        },
      });
    },
  });
}
  • promise
function getOneNews() {
  axios
    .get(topicsUrl)
    .then(function(response) {
      let id = response.data.data[0].id;
      return axios.get(topicOneUrl + id);
    })
    .then((res) => {
      render(res.data.data);
    })
    .catch(function(error) {
      console.log(error);
    });
}
  • async/await
async function getOneNews() {
  let listData = await axios.get(topicsUrl);
  let id = listData.data.data[0].id;
  let data = await axios.get(topicOneUrl + id);
  render(data.data.data);
}

online preview

Preview address: http://jsrun.net/s43Kp/embedded/all/light

problem? ?

If multiple asynchronous codes exist at the same time, what should be the order of execution? Which one is executed first, and which one is executed later?

Macro task and micro task

The division of asynchronous code, asynchronous code is divided into macro tasks and micro tasks.

macro task (don’t worry) Micro task (in a hurry)
<script> overall codePromise
setTimeout/setInterval

Event loop

EventLoopmind.png

Order of execution:

  1. Execute the overall code <script> (macro task)
  2. Perform all micro tasks
  3. Perform a macro task
  4. Execute rendering thread
  5. 2->3->2->3...sequentially loop (new macros and micro tasks are created in steps 2 and 3)

Repeatedly take out tasks from the macro task and micro task queues to execute.

to sum up

Because of the browser design, the JS thread and the rendering thread are mutually exclusive, so the JS thread is designed as a single thread.

Because of the blocking problem when a single thread performs some operations (such as network requests), all asynchronous.

Because of the asynchrony, asynchronous programming is produced, and thus there is a callback function.

Because the callback function is written too much, the callback hell will be generated, so there is a Promise writing method to solve the callback hell.

Since the ES7 standard, there has been a more elegant way of writing than Promise—async/await, which is also the ultimate solution for asynchronous programming.

Because JS code is divided into synchronous and asynchronous code, the execution order of synchronous code needless to say, execution from top to bottom.

But if there are multiple asynchronous codes, what is the order of execution? ?

In order to solve the problem of the execution order of multiple asynchronous codes, there is an event loop (EventLoop), which divides asynchronous tasks into macro tasks and micro tasks, and executes them in sequence according to the rules.

That's it!

Exercise

console.log("script start");
setTimeout(function() {
  console.log("timeout1");
}, 10);
new Promise((resolve) => {
  console.log("promise1");
  resolve();
  setTimeout(() => console.log("timeout2"), 10);
}).then(function() {
  console.log("then1");
});
console.log("script end");

Write the output of the log and give the reason.

reference

original article

九旬
1.1k 声望1.2k 粉丝

关注我,每周输出一篇前端技术文章,