Author: Huang Wei

NextTick of node asynchronous model

Is EventLoop clear?

I don’t think you get it, but don’t look down if you really think you do

When it comes to Eventloop, many people think of setTimeout, setInterval, Promise, and node has its own asynchronous apis

After reading the instructions here, there is a sentence that goes like this

When Node.js is started, it initializes event polling; Process the supplied input script (or drop it into the REPL, which is not covered in this article), which may call some asynchronous API function calls to schedule tasks to handle events, or call process.nexttick () and then start processing the event loop.

The diagram below shows an overview of the event cycle and the sequence of actions.

Each phase has a FIFO queue to perform the callback. While each phase is special, typically, when an event loop enters a given phase, it performs any operation specific to that phase, and then performs callbacks in the queue for that phase until the queue is exhausted or the maximum number of callbacks has been executed. When the # queue is exhausted or the callback limit is reached, the event loop moves to the next phase, and so on. Since more operations could be planned for any one of these operations, and new events processed in the polling phase are queued by the kernel, polling events can be queued when polling events are processed. Therefore, running callbacks for a long time can allow the polling phase to run a lot longer than the timer threshold. See the Timers and Polling section for more information.

NextTick: “When the queue is exhausted or the callback limit is reached, The event loop will move to the next phase.”

How do we prove that?

const Koa = require('koa');
const app = new Koa();

new Array(100000).fill('').map((v, i) => {
  app.use((ctx, next) => {
    new Array(100).fill(i).map((_v, _i) => {
      process.nextTick(() => {
          ctx.body = i
      })
    })
    next()
  })
})
app.listen(3000);
Copy the code

A simple Node service is started with 100,000 middleware registered in the service. Each middleware does the same thing, creating an array of length 100. The inner array responds with nextTick to ctx.body with the subscript value of the outer array

If you ignore the above statement, the result is 99999. Because the above middleware logic is continuous, only process.nextTick is an asynchronous API, so in order of main execution stack, micro task, macro task. Our final ctx.body response is 99999. Is that true or not? Not necessarily

The result is 2327

How does this 2327 come from V8 and OS scheduling? How does it come from V8 and OS scheduling? I don’t know, how about adjusting the number of middleware? We adjusted to 10,000 middleware

The author here tested the same result is 2327, but 3796 appeared once

So usually when you use nextTick, you can’t guarantee that it’s going to execute correctly.

And finally, an Event Loop