There are two things about Node.js asynchrony: non-blocking I/O and event loops. Because of these two factors, Node.js is considered high performance and can be used in online environments. Let’s take a look at node.js asynchronous mechanism and how to use it.

Non-blocking I/O for Node.js

  • The I/OInput/OutputA systematic oneInput and output.
  • The difference between blocking I/O and non-blocking I/O is whether or not the system can receive other inputs between input and output.

Take ordering meals as an example: when you go to the canteen to order meals, you need to wait in line. During this process, the aunt can only receive one person at a time. During this process, the aunt cannot receive other people’s orders, which is blocking I/O. And order go to the restaurant for dinner, can go to the restaurant and the waiter you want to eat tomato scrambled eggs, the waiter after down to the kitchen, after a table at this time to the other person said the waiter greeted the past want to eat small lobster, that is, on the dish to you before the waiter received the order of others, that this is a blocking I/O.

The key to understanding non-blocking I/O is this

  • Identify a system for Input/Output.
  • Consider whether other I/ OS can be performed during I/O.

So in the example of ordering meals, an Input/Output system is ordering food – kitchen (aunt) processing – serving food such a system can let you eat food; Ordering is Input, serving is Output. In this example, the key to determine whether the two are blocking or blocking is whether the ordering process can accept other ordering. It’s like if you order a fotiaoqiang, it may take a long time for the food to arrive, and then the people who come are ordering some simple dishes, one portion of fried noodles a minute, and they may go back and forth after several waves of people and they still haven’t delivered the food to you.

Node.js is used to manipulate the computer, and some operations, such as reading files, are time-consuming. If other I/O cannot be performed, the processing efficiency is very low, which is one reason node.js is non-blocking I/O.

Node.js event loop

Node.js initializes the event loop provided by Libuv when it is started. Each event loop contains six phases, which are executed repeatedly in the sequence shown in the following figure:

  • timersPhase: This phase is executedtimer(setTimeout,setIntervalThe callback
  • I/O callbacksPhase: Handles some of the few unexecuted I/O callbacks from the previous cycle
  • idle.preparePhase: Used internally by Nodes only
  • pollPhase: Get the new I/O event, where Node will block under appropriate conditions
  • checkPhase: ImplementationsetImmediate()The callback
  • close callbacksPhase: ImplementationsocketcloseEvent callback

Each phase has a first-in, first-out (FIFO) queue for callback execution. At each phase of the event loop, callback functions are removed from the corresponding callback queue and executed until either the queue is exhausted or the number of callbacks executed reaches the maximum.

The event loop then proceeds to the next phase, and the callback function is pulled from the queue corresponding to the next phase, and so on until the last phase of the event loop. The event loop will execute one by one until the process terminates.

The relationship between the six macroqueues and microqueues in the event loop is as follows: Microqueues execute between the phases of the event loop, or between the corresponding macrotasks of each phase of the event loop.

Here’s a particularly confusing version change:

  • Node10 and earlier: there are several macro tasks in the macro queue, and the micro tasks in the micro queue are not executed until all macro tasks in the macro queue are completed
  • For Node11 and later: Once a macro task in the corresponding macro queue is executed in a phase (setTimeout.setIntervalsetImmediateOne of the three, not including I/O, immediately executes the microtask queue, executes all the microtasks in the microqueue and then returns to the macro queue to execute the next macro task. It’sRun the same as the browser.

Node.js asynchronous programming –callback

  • Callback function format specification
    • error-first callback
    • node-style callback
  • The first parameter is thetaerrorThe following parameters are the result.
// The first argument is error capture
interview(function (err, res) {
  if (err) {
    console.log('cry')
    return;
  }
  console.log('smile')})function interview(callback) {
  setTimeout(() = > {
    if (Math.random() > 0.2) {
      callback(null.'success')}else {
      callback(new Error('fail'}})),500)}Copy the code

Asynchronous process control: callback hell, asynchronous concurrency, etc

  • npm:async.js; Can be achieved byasync.jsTo control asynchronous processes
  • thunk: a way of programming

Node.js asynchronous programming —Promise

  • You can read it literally,PromisePromise means promise. The current event cycle doesn’t give you results, but future events will give you results
  • It’s a state machine, and once the state is determined to beresolvedrejectedIt won’t change
    • pending: Initial state, state in which no result has been obtained
    • fulfilled / resolved: Success status
    • rejected: Failed state

Chain calls:.then and.catch

  • resolvedThe state of thePromiseIt’s going to call back the first one after that.then
  • rejectedThe state of thePromiseIt’s going to call back the first one after that.catch
  • Any onerejectedStatus and no following.catchPromiseWill cause a global error in the browser/Node environment
// State transitions for promises and then fetch content
const promise = new Promise((resolve, reject) = > {
  setTimeout(function () {
    resolve(3);
    // reject(new Error(4))
  }, 500)
})

promise.then(function (result) {
  console.log(result)
}).catch(function (err) {
  console.log(err)
})

setTimeout(() = > {
  console.log(promise)
}, 800)
Copy the code

Executing then and catch returns a new Promise, the final state of which is determined by the result of executing the callbacks to then and catch

  • If the callback function ends up beingthrowthePromiserejectedstate
  • If the callback function ends up beingreturnthePromiseresolvedstate
  • But if the callback function ends upreturnaPromisethePromiseAnd the callback functionreturnPromiseState consistency

Node.js asynchronous programming —async/await

  • async functionPromiseSyntax sugar encapsulation
  • The ultimate in asynchronous programming – write asynchronously in a synchronous manner
    • awaitThe keyword can be “pause”async functionThe implementation of the
    • awaitKeywords can be obtained synchronouslyPromiseExecution result of
    • try-catchYou can getawaitGet the error
(async function () {
  await findJob()
  console.log('trip')
})()

async function findJob() {
  try {
    // Three rounds of interviews
    await interview(1);
    await interview(2);
    await interview(3);
    console.log('smile')}catch (e) {
    console.log('cry at ' + e.round)
  }
}

// Conduct the first round of interviews
function interview(round) {
  return new Promise((resolve, reject) = > {
    setTimeout(() = > {
      if (Math.random() < 0.2) {
        const error = new Error('failed');
        error.round = round;
        reject(error);
      } else {
        resolve('success'); }},500)})}Copy the code

This is a function that exists through the event loop.

conclusion

  • Understanding non-blocking I/O is about identifying a system that does I/O and then thinking about whether it can do other I/ OS.
  • Node.js event loops run the same as browser event loops on Node11 and later.
  • The specification for node.js asynchronous programming is that the first parameter iserror, the latter is the result.
  • PromiseIs aThe state machine, the initial state ispending, once the state is determined asresolvedrejectedIt won’t change. It can pass.then.catchMake a chain call.
  • async/await Write asynchronously in a synchronous mannerIs the ultimate solution for asynchronous programming.