Antecedents feed

In the interview two days ago, I asked about the functions of async and await and the usage scenarios in both interviews.

I thought afterwards why we use async and await. How do they compare to using callbacks and promises to handle asynchrony?

I summarize the ideas of this article as follows:

  1. Handle asynchrony with callback functions
  2. Handle asynchrony with promises
  3. Handle asynchrony with Promise + generator + CO
  4. Handle asynchrony with await and async

Consider a scenario where asynchrony is required

TXT to get the path of name. TXT, and then read name. TXT to get the path of score. TXT, and then read score. TXT to get the score

1. Callback functions solve asynchrony

let fs = require("fs");
function read(filepath){
   fs.readFile(filepath,'utf8',(err,data)=>{
       if(! err){ fs.readFile(data,'utf8',(err,data)=>{
               if(! err){ fs.readFile(data,'utf8',(err,data)=>{
                       console.log(data);
                   })
               }
           })
       }
   })
}
read('./data/number.txt');
Copy the code

While callback functions can solve the problem of asynchronous operations, they have the following disadvantages:

  1. The callback hell
  2. Can’t try catch
  3. Cannot synchronize concurrent asynchronous results

2. Handle asynchrony with promises

function read(path){
    return new Promise((resolve,reject) = >{
        fs.readFile(path,'utf8',(err,data)=>{
            if(err){
                reject(err);
            }else{
                resolve(data);
            }
        })
    })
}
read('./data/number.txt').then((data) = >{
    return read(data);
}).then((data) = >{
    return read(data);
}).then((data) = >{
	console.log(data);
})
Copy the code

It’s much cleaner when you use Promise, but it’s a little cumbersome to call then multiple times

Then we further use Promise+ Generator +Co to optimize

3.Promise+ Generator +Co handle asynchrony

Promise

let fs = require("fs");
function readFile(path){
    return new Promise((res,rej) = >{
        fs.readFile(path,'utf8',(err,data)=>{
            if(err){
                rej(err)
            }else{ res(data); }})})}Copy the code

The generator function

function *read(path){
    let val1 = yield readFile(path);
    let val2 = yield readFile(val1);
    let val3 = yield readFile(val2);
    return val3;
}
Copy the code

Co function

function Co(oIt){
    return new Promise((res,rej) = >{
        let next = (data) = >{
            // Generator each time next returns an object {value:,done:,}
            // Value is a promise object,
            let {value,done}=oIt.next(data);
            if(done){
                // As long as done is not true, the generator function is not finished
                res(value);
            }else{
                value.then((val) = >{
                // Value is a promise object,
                // So we can pass the result val to next
                // recursive processingnext(val); }) } } next(); })}Copy the code

Results:

let readNum = read('./data/number.txt');
Co(readNum).then((val) = >{
    console.log(val);
})
Copy the code

After such modification, it is indeed more concise, but the trouble is, either we write a Co function, or to introduce a Co NPM package, is there a better way

Next, optimizations with await and async

4.await and async processing async

//async indicates that the following function has an asynchronous operation
// And this function will eventually return a Promise object
async function read(path){
//await returns the processing result of subsequent promise objects
    let val1 = await readFile(path);
    let val2 = await readFile(val1);
    let val3 = await readFile(val2);
    return val3;// even if val3 is a string
    // When returned, it is also wrapped as a Promise object
}
read('./data/number.txt').then((val) = >{
	console.log(val);
})
Copy the code

With await and async there is no need to write co functions and it is easier to understand to use

If you translate with Babel, you will find that the underlying implementation of await and async is promise+ Generator + CO

1. Await and async can use try catch

Asynchronous callback functions cannot catch errors with a try catch

let fs = require("fs");
function read (){
    fs.readFile('./data/number.txt'.'utf8',(err,data)=>{
        throw Error("Something went wrong.");
        
        if(err){
            console.log(err);
        }else{
            console.log(data); }})}try{
    read();
}catch(e){
    console.log("This is an error message.",e);
}
Copy the code

A callback cannot use a try catch if the error message “this is an error message” is missing

And await and ASNYC

async function read(url){
    try{
        let val1 = await readFile(url);
    	let val2 = await readFile(val1);
    	let val3 = await readFile(val2);
    	return val3
    }catch(e){
        console.log("This is an error message.",e); }}let readNum = read('./data/number.txt1');
readNum.then((val) = >{
    console.log(val);
})
Copy the code

After execution, you can see that the error message has a “this is an error message” field, proving that with async and await asynchronous processing, the error message can be caught.

2. Async and await the results of synchronous concurrent asynchrony

In general we have a promise.all method for handling synchronous concurrency

Promise.all([readFile('./data/1.txt'),readFile('./data/2.txt'),readFile('./data/3.txt')]).then((val) = >{
    console.log(val);
},(err)=>{
    console.log(err);
})
Copy the code

But if one of the asynchronous requests has an error and we need to find the error, promise.all will not be implemented

This can be done with await and async

async function read1(){
    let val1 = null;
    try{
        val1 = await readFile('./data/1.txt');
        console.log(val1);
    }catch(e){
        console.log("This is an error message."E); }} read2,read3function readAll(. args){
    args.forEach((ele) = >{ ele(); })}Copy the code

As soon as one of the asynchrons has an error, we can find the error.

conclusion

Author: Hu Zhiwu

Time: 2019/7/8

If there are any mistakes in this article, please correct them!