The so-called “asynchronous” simply means that a task is divided into two parts, first performing the first part, then switching to other tasks, and then returning to the second part when we are ready. For example, we can do a lot of things when boiling water, and wash our face with water after boiling water. This discontinuous execution is called asynchrony. Accordingly, continuous execution is called synchronization. For example, in the process of boiling water, we wait for the water to boil and do nothing else.

1. Higher-order functions

Functions as first-class citizens can satisfy at least two conditions as arguments and return values for higher-order functions

  • Takes one or more functions as input
  • Output a function

1.1 Preset Parameters

let isType = function(type,obj){
    return Object.prototype.toString.call(obj) ===`[object ${type}]`
}
console.log(isType('Object', {})); console.log(isType('Object', {})); console.log(isType('String'.'hello'));
console.log(isType('String'.'hello')); // We find that we need to pass in a type every time we call isType, so we can batch out the available functions firstlet isType = function(type) {return function(obj){
        return Object.prototype.toString.call(obj) ===`[object ${type}] `}}let isObject = isType('Object');
let isString = isType('String');
console.log(isObject({}));
console.log(isObject({}));
Copy the code

1.2 Preset functions

function after(times,cb){
    return function() {if(--times === 0){ cb(); }}}let eat = after(3,function(){console.log('Eaten up')}); eat(); eat(); eat(); // Execute our preset function when the number of calls reaches our preset numberCopy the code

Now that we have a better understanding of functions, let’s move on to an asynchronous solution.

2. Callback functions

The so-called callback function is to write the second section of the task in a separate function, and wait until the task is executed again, directly call the function. We introduced a common node asynchronous method called readFile that can be used to read files.

fs.readFile(filename, function (err, data) {
  if (err) throw err;
  console.log(data);
});
Copy the code

The first argument to the node callback is an error-first callbacks.

2.1 Application of the callback function

function read(callback){
    setTimeout(function() {let result = 'zpfx'; callback(result); })}read(function(data){
    console.log(data);
});
Copy the code

We can use callback functions to solve asynchronous problems

3. Callbacks

  • Asynchrony does not support try/catch, and the callback function is fetched in the next event loop, so the error object is usually preset in the first argument of the callback function
  • Callback hell problem, asynchronous multilevel dependencies in case of very deep nesting, code difficult to read maintenance
  • Multiple asynchrons get the results of all asynchrons at one time
  • The result cannot be returned by return

4.Promise

I’ll make a Promise to you after a certain amount of time. When is it used over a period of time? The answer is asynchronous operations, which are things that take a long time to produce results, such as network requests, reading local files, etc

4.1 Three states of Promise

For example, when my daughter-in-law says she wants to buy a bag, she has to “wait” for my reply. I can buy it in two days. If I buy it, it means “success”; if I refuse, it means “failure”

  • Pending Promise Specifies the initial state of an object instance when it is created
  • This can be interpreted as a state of success
  • Rejected = Rejected

The then method is used to specify the actions that will be performed when the state of the Promise object changes. The first function (onFulfilled) will be performed in resolve, and the second function (onFulfilled) will be performed in reject.

4.2 structure Promise

Promise’s method is executed immediately

let promise = new Promise(() => {
    console.log('hello');
}); 
console.log('world'); 
// hello
// world
Copy the code

4.3 PROMISE can also represent a future value

const fs = require('fs');
let  promise = new Promise((resolve, reject) => {
    fs.readFile('./content.txt'.'utf8'.function (err, data)  {
        if (err) returnreject(err); resolve(data); })}); promise.then(data => { console.log(data); }); promise.then(data => { console.log(data); }); // A promise instance can be called multiple timesthenWhen successful, the results are executed in sequenceCopy the code

4.4 represents a value that will not be returned

const fs = require('fs');
letpromise = new Promise((resolve, reject) => { }); promise.then(data => { console.log(data); // represents a value that will not be returned});Copy the code

4.5 Cases of purchasing packages

function buyPack()  {
    return new Promise((resolve, reject) => {
        setTimeout(function  ()  {
            var  random = Math.random();
            if(random > 0.5) {resolve('buy');
            } else {
                resolve('don't buy');
            }
        }, 2000)
    })
}
buyPack().then(data => {
    console.log(data);
}, data => {
    console.log(data);
}); 
Copy the code

4.6 Error causes Reject to trigger

Failure can be caught using the second argument to then, or through the catch function

function buyPack()  {
    return new Promise((resolve, reject) => {
        throw new Error('no money')
    })
}
buyPack().then(data => {
    console.log(data);
}, data => {
    console.log(data);
}); 
Copy the code

5. Fix callback hell

Back to business, let’s solve the first problem with promise: “Callback hell.”

// 1. TXT => 2. TXT // 2. TXT => I am handsomelet fs = require('fs');
function read(){
    fs.readFile('./1.txt'.'utf8'.function(err,data){
        if(err) return console.log(err);
        fs.readFile(data,'utf8'.function(err,data){
            if(err) returnconsole.log(err); console.log(data); // I am handsome})})}read(a);Copy the code

Rewrite the Promise form

let fs = require('fs');
function read(file){
    return new Promise(function(resolve,reject){
        fs.readFile(file,'utf8'.function(err,data){
            if(err) returnreject(err); resolve(data); })})}read('./1.txt').then(function(data){
    return read(data);
}).then(function(data){
    console.log(data)
}).catch(function(err){
    console.log(err)
});
Copy the code

When a promise is returned in the first THEN, the result of the returned promise is passed to the next THEN. This is the famous chain call.

6. Result of asynchronous synchronization

We summarize the results of multiple asynchronous requests at the same time

// 1.txt => template
// 2.txt => data
let fs = require('fs');
let result = {}
function out(key,data) {
    result[key] = data;
    if(Object.keys(result).length === 2){
        console.log(result)
    }
}
fs.readFile('./1.txt'.'utf8'.function (err, data) {
    if (err) return console.log(err);
    out('template',data);
})
fs.readFile('./2.txt'.'utf8'.function (err, data) {
    if (err) return console.log(err);
    out('data',data); }); // This is not a good way to declare the global object, and the number of successes is also written dead, we can use partial functions to overwriteCopy the code
let fs = require('fs');
let result = {}
function after(times,cb) {
    let result = {}
    return function(key,data){
        result[key] = data;
        if(Object.keys(result).length === times){
            cb(result)
        }
    }
}
let out = after(2,function(data){
    console.log(data)
})
fs.readFile('./1.txt'.'utf8'.function (err, data) {
    if (err) return console.log(err);
    out('template',data);
})
fs.readFile('./2.txt'.'utf8'.function (err, data) {
    if (err) return console.log(err);
    out('data',data);
});
Copy the code

Finally, we can use the promise.all method to simplify

let fs = require('fs');
function read(file){
    return new Promise(function(resolve,reject){
        fs.readFile(file,'utf8'.function(err,data){
            if(err) return reject(err);
            resolve(data);
        })
    })
}
Promise.all([read('1.txt'),read('2.txt')]).then(([template,data])=>{ console.log({template,data}) }); The promise. all method returns the results in the order in the array, regardless of which of the two promises completes firstCopy the code

7.Promise.race

Accepts an array of Promise instances and returns a Promise instance whose state transitions depend on the state changes of the parameter’s Promise instance. When either instance of the parameter is in the resolve state, the returned Promise instance changes to the resolve state. If either instance of the argument is reject, the returned Promise instance becomes REJECT.

Promise.race([read('1.txt'),read('2.txt')]).then(data=>{
    console.log({template,data})
},(err)=>{
    console.log(err)
});
Copy the code

8.Promise.resolve

Return an instance of Promise in the resolve state

Promise.resolve('success').then(data=>{ 
    console.log(data);
});
Copy the code

9.Promise.reject

Return a Promise instance in reject state

Promise.reject('failure').then(data=>{ 
   console.log(data); 
},err=>{ 
console.log(err); 
}) 
Copy the code

In the next section we will continue to explain the use of generator and async/await, as well as the implementation principle of Promise. You can give me a tip if you support me