js execution order and event loop

Because js is a single-threaded language, when encountering asynchronous tasks (such as ajax operations, etc.), it is impossible to wait for the asynchronous completion and continue execution. During this period, the browser is idle. Obviously, this will lead to a huge waste of resources. .

Execution stack

When a function is executed, the user clicks the mouse once, Ajax is completed, an image loading is completed and other events occur, as long as the callback function is specified, these events will enter the execution stack queue when they occur, waiting for the main thread to read, follow first-in first Out of principle.

Main thread

One thing to be clear is that the main thread is a different concept from the execution stack. The main thread specifies which event in the execution stack is currently executed.

Main thread loop: That is, the main thread will continuously read events from the execution stack, and will execute all synchronization codes in the stack.

When an asynchronous event is encountered, it will not always wait for the asynchronous event to return the result, but will hang the event in a different queue from the execution stack, which we call the Task Queue.

After the main thread executes all the code in the execution stack, the main thread will check whether there are tasks in the task queue . If so, the main thread will execute the callback functions in the task queue in turn.



The execution order of js code, new Promise, Promise.then, Promise.all().then(), process.nextTick in the global scope

Since the new Promise will be executed immediately, the code inside will be executed in sequence. The corresponding order is: sequential js code --> new Promise --> sequential js code (after the execution of global js and new Promise) --> all process.nextTick --> Promise().then( ) --> Promise.all().then()

console.log(1);// 顺序-1

Promise.all([new Promise(resolve => {
    
    
	console.log(2);// 顺序-2
	resolve(100);
})]).then(values => {
    
    
  console.log(values);// 顺序- 10
});

process.nextTick(() => {
    
    
  console.log(6);// 顺序- 6
});

new Promise((resolve) => {
    
    
  console.log(3);// 顺序-3
  resolve('3-1');
}).then(values => {
    
    
  console.log(values);// 顺序- 8
});

console.log(4);// 顺序- 4

new Promise((resolve) => {
    
    
  console.log(5);// 顺序- 5
  resolve('5-1');
}).then(values => {
    
    
  console.log(values);// 顺序- 9
})
process.nextTick(() => {
    
    
  console.log(7);// 顺序- 7
})

It involves setTimeout, and the timer has new Promise, Promise.then, and Promise.all.

The execution order of this case is executed after the first case has been executed. The execution sequence is:
multiple timers have the same time: setTimeout is executed in order. The order of execution in the timer is to execute js code sequentially --> new Promise --> ordered js code (after js and new Promise are executed) --> all process.nextTick --> Promise().then () --> Promise.all().then(). This is actually repeating the order of execution in the first case.

setTimeout(() => {
    
    
  console.log("setTimeout1");// 顺序-- 1
  new Promise((resolve) => {
    
    
    console.log('setTimeout1 --- Promise');// 顺序-- 2
    resolve('Promise-1');
  }).then((values) => {
    
    
    console.log(values);// 顺序-- 5
  });
}, 0)
setTimeout(() => {
    
    
  console.log("setTimeout2");// 顺序-- 3
  new Promise((resolve) => {
    
    
    console.log('setTimeout2 --- Promise');// 顺序-- 4
    resolve('Promise-2');
  }).then((values) => {
    
    
    console.log(values);// 顺序-- 6
  });
}, 0)

Macro task and micro task

For the tasks in the message queue, they are divided into two categories:

  • Macrotask (macrotask): setTimeout, setInterval
  • Microtask: promise

The macro task contains the micro task, and the execution of one macro task is completed, and the next macro task is started.

    console.log("a")
    let r = new Promise(function (resolve, reject) {
    
    
      console.log("b");
      resolve()
    });
    r.then(() => console.log("c"));
    setTimeout(() => {
    
     console.log("d") }, 0)
    setTimeout(() => {
    
     console.log("e") }, 1000)
    console.log("f")

Look at these few lines of code

  1. Started to execute, found some code, put it into a macro task
  2. Execute a first
  3. Execute b
  4. It is found that the asynchronous operation then belongs to the micro task, and it is added to the queue of the micro task in the current macro task
  5. It is found that the timer d and setTimeout belong to the macro task and are added to the queue of the macro task
  6. It is found that the timer e and setTimeout belong to the macro task and are added to the queue of the macro task
  7. Execute f
  8. The code has been executed, start to execute the micro task queue, and print out c
  9. The execution of the micro task queue is completed, and the next macro task queue is executed
  10. Print out d directly, there are no other micro tasks, and start to execute the next macro task queue
  11. Print out e, all macro tasks are completed

Guess you like

Origin blog.csdn.net/weixin_53687450/article/details/112591413