Introduction to the

Because JavaScript is single-threaded by default, this means that the code cannot create new threads to execute in parallel. However, for JavaScript that initially runs in the browser, the single-threaded synchronous execution environment is obviously not sufficient for page clicks, mouse movements and other user-responsive functions. Instead, the browser implements a set of APIs that allow JavaScript to respond asynchronously to page request events in the form of callbacks.

Further, NodeJS introduces non-blocking I/O, thus extending the concept of asynchrony to file access, network calls, and more.

Today, we’ll take a closer look at the pros and cons and trends of asynchronous programming.

Synchronous asynchronous and blocking non-blocking

Before discussing asynchronous programming in NodeJS, let’s discuss the confusing concepts of synchronous, asynchronous, blocking, and non-blocking.

The so-called blocking and non-blocking refers to whether the process or thread needs to wait while performing operations or data reading and writing, and whether other operations can be carried out during the waiting process.

If a wait is required, and the thread or process can do nothing but wait stupidly while waiting, the operation is said to be blocking.

On the other hand, if a process or thread can perform other operations in the process of performing an operation or reading or writing data, then the operation is said to be non-blocking.

Synchronous and asynchronous refer to the way data is accessed. Synchronous refers to the active reading of data, which may be blocked or non-blocked. Asynchronous means that there is no need to actively read data, is a passive notification.

Obviously, a callback in JavaScript is a passive notification, which we might call an asynchronous call.

Callbacks in JavaScript

Callbacks in JavaScript are a very typical example of asynchronous programming:

document.getElementById('button').addEventListener('click', () => { console.log('button clicked! '); })

In the code above, we added a click event listener to the Button. If we hear a click event, we will launch a callback function to print the corresponding information.

A callback function is a normal function, except that it is passed as an argument to an addEventListener and is called only when an event is fired.

The setTimeout and setInterval we talked about in the last article are actually asynchronous callbacks.

Error handling of callback functions

How do you handle callback error messages in NodeJS? In NodeJS, the first argument in any callback function is an error object, and we can determine whether this error object exists or not and handle the error accordingly.

Fs. ReadFile ('/file. Json, (err, data) = > {the if (err! == null) {// handle error console.log(err) return} // If there is no error, the data will be processed. console.log(data) })

The callback hell

While JavaScript callbacks are excellent, they effectively solve the problem of synchronous processing. Unfortunately, we can get into callback hell if we need to rely on the return value of the callback function to do the next operation.

Calling callback hell is a bit of an exaggeration, but it also reflects the problems with callback functions.

fs.readFile('/a.json', (err, data) => { if (err ! == null) { fs.readFile('/b.json',(err,data) =>{ //callback inside callback }) } })

What’s the solution?

Don’t be afraid that ES6 has introduced Promise and ES2017 has introduced Async/Await to solve this problem.

The Promise in ES6

What is a Promise

Promise is a solution to asynchronous programming that makes more sense and is more powerful than the traditional “callback functions and events” solution.

A Promise is simply a container that holds the result of an event (usually an asynchronous operation) that will end in the future.

Syntactically, a Promise is an object from which you can retrieve messages for asynchronous operations.

The characteristics of the Promise

Promise has two characteristics:

  1. The state of the object is not affected by the outside world.

A Promise object represents an asynchronous operation that can have three states: Pending, Resolved, and Rejected.

Only the result of an asynchronous operation can determine the current state, which cannot be changed by any other operation.

  1. Once the state changes, it doesn’t change again, and at any time you can get this result.

There are only two possibilities for a Promise object to change state: from Pending to Resolved or from Pending to Rejected.

This is quite different from an Event, which has the characteristic that if you miss it and listen to it again, you will not get the result.

The advantages of the Promise

Promise expresses asynchronous operations as a flow of synchronous operations, avoiding layers of nested callbacks.

Promise objects provide a uniform interface, making it easier to control asynchronous operations.

The shortcoming of Promise

  1. You cannot cancel the Promise, which is executed as soon as you create it, and cannot be canceled halfway.
  2. If you do not set the callback function, errors thrown inside the Promise will not be reflected outside.
  3. When Pending, it is impossible to know where the progress is (just started or about to be completed).

The use of the Promise

The Promise object is a constructor that generates a Promise instance:

var promise = new Promise(function(resolve, reject) { // ... Some code if (/* Aasync */){resolve(value); } else { reject(error); }});

A promise can be preceded by a then operation, and a then operation can be preceded by two function arguments. The first is the value of the resolve used when the promise was built, and the second is the error of the reject used when the promise was built.

promise.then(function(value) { 
// success 
}, function(error) { 
// failure }
);

Let’s look at a concrete example:

function timeout(ms){
    return new Promise(((resolve, reject) => {
        setTimeout(resolve,ms,'done');
    }))
}

timeout(100).then(value => console.log(value));

The Promise calls a setTimeout method that periodically triggers the resolve method and passes in the done parameter.

Finally, the program prints done.

The order in which Promises are executed

The Promise is executed as soon as it is created. The method in Promise. Then, however, will wait until a call cycle has passed, as shown in the following example:

let promise = new Promise(((resolve, reject) => { console.log('Step1'); resolve(); })); promise.then(() => { console.log('Step3'); }); console.log('Step2'); Output: Step1 Step2 Step3

Async and await

Promise is fine, of course, and we convert callback hell into chained calls. We use a Then to connect multiple Promises together. The result of the first Promise resolve is the argument to the Then in the next Promise.

What’s the downside of chained calls?

For example, if we resolve a value from a Promise, we need to do some business logic processing based on that value.

If the business logic is long, we need to write long business logic code in the next THEN. This makes our code look very redundant.

So is there a way to directly return the result of resolve in a promise?

The answer is “await”.

When a promise is preceded by an await, the calling code will stop until the promise is resolved or rejected.

Note that await must be placed in the async function. Let’s look at an example of async and await:

Const logAsync = () => {return new Promise(resolve) => {setTimeout(() => resolve(' Ur '), 5000)})}

Above we defined a Logasync function that returns a Promise. Since the Promise uses setTimeout internally to resolve, we can think of it as asynchronous.

To get the value of resolve using await, we need to put it in an async function:

const doSomething = async () => {
  const resolveValue = await logAsync();
  console.log(resolveValue);
}

The order in which async is executed

“Await” is actually waiting for the result of a promise’s resolve. Let’s combine the above examples:

Const logAsync = () => {return new Promise(resolve) => {setTimeout(() => resolve()), 1000) }) } const doSomething = async () => { const resolveValue = await logAsync(); console.log(resolveValue); } console.log('before') doSomething(); console.log('after')

The above example output:

B: Before after

As you can see, aysnc is executed asynchronously, and its order is after the current period.

The characteristics of the async

Async makes any function that follows it a Promise, even if it doesn’t explicitly return a Promise.

const asyncReturn = async () => {
    return 'async return'
}

asyncReturn().then(console.log)

Since only a Promise can be followed by a then, we can see that async wraps a normal function as a Promise:

const asyncReturn = async () => {
    return Promise.resolve('async return')
}

asyncReturn().then(console.log)

conclusion

Promise avoids callback hell by paraphrasing callback inside callback into chained invocation form of a then.

But chained calls are not easy to read and debug. So async and await.

Async and await change chained calls to a syntax similar to the sequential execution of a program, making them easier to understand and debug.

Let’s look at a comparison, starting with the use of Promise:

Const getUserInfo = () => {return fetch('/ User. json') // Get the user list. Then (response => response .then(users => fetch(' /users/${user.name} ')).then(userResponse =>).then(userResponse => Json} getUserInfo()

Overwrite this to async and await:

Const getUserInfo = async () => {const response = await Fetch ('/ User. json') // Get user list const Users = await Json () // Parse json const user = users[0] // Select the first user const userResponse = await fetch(' /users/${user.name} ') // Const UserData = await UserResponse. json()} getUserInfo()

You can see that the business logic becomes clearer. At the same time, we get a lot of intermediate values, which is easy for us to debug.

The Flydean program stuff

This paper links: http://www.flydean.com/nodejs-async/

This article is from Flydean’s blog

Welcome to pay attention to my public number: “program those things” the most popular interpretation, the most profound dry goods, the most concise tutorial, many you do not know the tips you to find!