Interpretation execution order setTimeout, promise.then, process.nextTick, setImmediate of

Recently encountered a few interesting questions looking at "Node.js Debugging Guide" when the order is executed on setTimeout, promise.then, process.nextTick, setImmediate of. Today, we are taking the time to record the principles and knowledge of solving the problem under analysis and behind.
Topics are as follows:

// 题目一:
setTimeout(()=>{
    console.log('setTimeout')
},0)
setImmediate(()=>{
    console.log('setImmediate')
})
// 题目二:
const promise = Promise.resolve()
promise.then(()=>{
    console.log('promise')
})
process.nextTick(()=>{
    console.log('nextTick')
})
// 题目三:
setTimeout (() => { 
  console.log(1)
},0)
new Promise((resolve,reject) => { 
  console.log(2)
  for(let i = 0; i <10000; i++) {
      i === 9999 && resolve()
  }         
  console.log(3) 
}).then(() => { 
  console.log(4)
})
console.log(5)
// 题目四
setInterval(()=>{
    console.log('setInterval')
},100)
process.nextTick(function tick(){
    process.nextTick(tick)
})

Before analyzing these questions it is necessary to first understand node.js event loop

Event Loop Event Loop

Event Loop we can be simply understood as follows:

  1. All tasks are performed on the main thread to form a stack execution (Execution Context Stack)
  2. There is also a task queue (Task Queen) in addition to the main thread, the system is asynchronous tasks into task queue, then the main thread continues to execute subsequent tasks
  3. Once all of the tasks in the execution stack is finished, the system reads the task queue. If you then asynchronous task has ended the wait state, will enter the execution stack from the task queue, resume execution
  4. The main thread above the third step is repeated
    to read the third step in the above task queue includes six stages
  • timers: execution setTimeout () and setInterval () callback in due
  • I / O callbacks: one cycle have a small number of I / O callback will be delayed until this round of this phase
  • idle, prepare: internal calls only
  • poll: the most important stage, perform I / O callback, under certain conditions node will be blocked at this stage
  • check: callback execution setImmediate () of
  • close callbacks: performing callback close event, e.g. socket.on ( 'close', func)

Each stage has a FIFO queue callback, when performing Event Loop to this stage, it will come up from the current phase of the task into a queue execution stack execution, the number of empty or callback queue task execution reaches the limit after, Event Loop will enter the next stage

poll phase

poll stage has two main functions, as follows:

  1. When the timer expires timers, perform callback timer (setTimeout and setInterval) of
  2. To poll the queue inside the I / O callback
    if Event Loop phase into the poll, and the code Timer is not set, the following situation may occur:
  • If the callback poll queue is not empty, then the Event Loop will be performed synchronously in the callback queue, until the queue is empty, or the implementation of the system reaches the upper limit
  • If the poll queue is empty, the following may occur:
    • If the code used in setImmediate (), then the Event Loop phase will end poll and check into the stage, the stage of execution check code
    • If you do not use setImmediate code (), then the Event Loop will be blocked at this stage, waiting for the callback join poll queue, if callback come immediately executed

Once the poll queue is empty, the Event Loop will check timers, if there is time timer expires, the Event Loop timers will return to the stage, and then perform the timer queue

Event loop principle

  1. node initialization
    1. Initialize node environment.
    2. Enter the code execution.
    3. Execution process.nextTick callback.
    4. Execution microtasks.
  2. Into the event-loop
    1. Enter timers stage
      • Check whether the timer has expired queue timer callback if the callback timer expires timerId performed in ascending order.
      • Check for process.nextTick task, if there is, all of the implementation.
      • Check for microtask, if there is, all of the implementation.
      • Exit the stage.
    2. IO callbacks into the stage.
      • Check for a pending I / O callbacks. If so, perform the callback. If not, exit the stage.
      • Check for process.nextTick task, if there is, all of the implementation.
      • Check for microtask, if there is, all of the implementation.
      • Exit the stage.
    3. Enter idle, prepare stage:
      • These two stages of our relationship is not programmed, for the time being refrain from that.
    4. Enter phase poll
      • First check whether there has not been completed callback, if there is, then the two cases.
        • The first case:
          • If one is available callback (callback contains the expiration of a timer available and some IO events, etc.), perform all of the available callback.
          • Check for process.nextTick callback, if there is, all of the implementation.
          • Check for microtaks, if there is, all of the implementation.
          • Exit the stage.
        • The second case:
          • If no callback.
          • Check for immediate correction, and if so, exit poll stage. If not, at this stage blocking, waiting for a new event notification.
      • If you have not completed the callback does not exist, exit poll stage.
    5. Check into the stage.

      • If there is immediate callback, all immediate callback is executed.
      • Check for process.nextTick callback, if there is, all of the implementation.
      • Check for microtaks, if there is, all of the implementation.
      • Exit check stage
    6. Into the closing stages.

      • If there is immediate callback, all immediate callback is executed.
      • Check for process.nextTick callback, if there is, all of the implementation.
      • Check for microtaks, if there is, all of the implementation.
      • Exit closing stages
    7. Check for active handles (timers, IO event handlers, etc.).

      • If so, continue to the next cycle.
      • If not, the end of the event loop, exit the program.

By introducing the above event loop we already know that enforcement mechanisms setTimeout setImmediate, but did not introduce process.nextTick () and promise.then (). Here we also need to know the concept of macro and micro-task mission

Macro task Macrotask

Macrotask refers Event Loop task performed in each stage of
the macrotask comprising Script (whole codes), setTimeout, setInterval, setImmediate, I / O, UI renderin

Micro task Microtask

Micro Event Loop task is a task performed between each stage
micro tasks include process.nextTick, Promise, Object.observe, MutationObserver

Micro-macro task execution order of tasks and FIG.

The green tile represents Event Loop various stages of execution of a macro task, pink arrow indicates the micro task execution

Here we come to understand that the above analysis of several questions
the subject is a result of execution:

setTimeout
setImmediate
//或者
setImmediate
setTimeout

Why inconclusive results do? We know setTimeout callback function is executed timer stage, setImmediate callback function executes in check stage. But from the beginning of the event loop to the timer stage it will consume a certain amount of time, so there will be two situations:

  1. If the preparation time before the timer than 1ms, timer stage (setTimeout) callback function is executed
  2. If the preparation time before the timer is less than 1ms, the check execution stage (setImmediate) callback function, the next event loop cycles in the execution stage function timer

The results are subject II

nextTick
promise

Although here and process.nextTick, like, promise.then will also register a callback function to microtask, but process.nextTick of microtask queue always take precedence over microtask queue execution promise of
the results of III is entitled

2
3
5
4
1

Promise constructor is executed synchronously, so the first print 2, 3, 5 in print, the next event loop to perform micro tasks callback promise.then, the print 4, and then enter the next cycle event callback timer stage 1 print

The results of four topics are
never printed setInterval

process.nextTick will infinite loop, the event loop blocked microtask stage, lead to other macrotask stage of the event loop callback function has no opportunity to perform
solution is usually used setImmediate instead of process.nextTick.
execution setImmedaite will be immediate when registering to within setImmediate the next event check stage loop, so have the opportunity to perform other macrotask

Thus finally the node.js event loop macro and micro job task analysis clearly

Guess you like

Origin www.cnblogs.com/jesse131/p/11708233.html