Following on from the previous article on the use of Generator+co juejin.cn/post/684490… Here we continue with the js async await method.

Async is short for asynchronous. Async is used to declare that a function is asynchronous, and await is used to wait for an asynchronous method to complete. Await can only appear in async functions

As in the previous example of reading a file, rewrite as

let bluebird = require('bluebird');
let fs = require('fs');
let read= bluebird.promisify(fs.readFile); //await a Promise object after the await command. The result may be //rejected, so it is better to await the await command in try... In the catch block. asyncfunction r(){
    try{
        let content1 = await read('1.txt'.'utf8');
        let content2 = await read(content1,'utf8');
        return content2;
    }catch(e){ 
        console.log('err',e)
    }
}

r().then(function(data){
    console.log('data',data);
},function(err){
    console.log('err1',err);
})
Copy the code

Async await is written in much the same way as generator. Replace the asterisk (*) of generator functions with async and yield with await

However async improves on the Generator function:

1. Built-in actuators: Generator functions must be executed by actuators, hence the CO library, while async functions come with actuators. In other words, async functions perform exactly as normal functions do.

2. Better semantics: async and await are clearer than asterisks and yield. Async means that there is an asynchronous operation in a function, and await means that the following expression needs to wait for the result.

3, wider applicability: According to the co library convention, yield can only be followed by Thunk or Promise, while async can be followed by await and Promise and primitive values (numeric, string, Boolean).

Async functions are so new that they are not in ES6, but in ES7. At present, it is still in the proposal stage, but the transcoders Babel and ReGenerator are supported and can be used after transcoding.

The role of async

The async function is responsible for returning a Promise object. If an async function returns an immediate Promise, the async function wraps the immediate Promise object with promise.resolve (). If async does not return a value, it returns promise.resolve (undefined).

What is await waiting for

We usually await an async function with await, but syntactically, await is an expression that evaluates to a Promise object or other value. Therefore, after await, we can actually receive ordinary function calls or direct quantities

If an await waits for something other than a promise object, the result of the following expression is what it waits for; If it is a promise object, await will block the following code, and the promise object resolve will get the value of resolve as the result of an await expression although await blocks, await in async, async does not block, All of its internal blocking is wrapped in a Promise object and executed asynchronously

Async Await usage scenario

In the example above, the advantages of Async Await are shown when a promise chained call is needed;

If a business needs to be done in steps, each step is asynchronous and depends on the result of the execution of the previous step, or even on the result of each previous step, it can be done with Async Await

function takeLongTime(n) {
    return new Promise(resolve => {
        setTimeout(() => resolve(n + 200), n);
    });
}
function step1(n) {
    console.log(`step1 with ${n}`);
    return takeLongTime(n);
}
function step2(m, n) {
    console.log(`step2 with ${m} and ${n}`);
    return takeLongTime(m + n);
}
function step3(k, m, n) {
    console.log(`step3 with ${k}.${m} and ${n}`);
    return takeLongTime(k + m + n);
}

async function doIt() {
    console.time("doIt");
    const time1 = 300;
    const time2 = await step1(time1);
    const time3 = await step2(time1, time2);
    const result = await step3(time1, time2, time3);
    console.log(`result is ${result}`);
    console.timeEnd("doIt");
}

doIt();
Copy the code

If I use promise

function doIt() {
    console.time("doIt");
    const time1 = 300;
    step1(time1)
        .then(time2 => {
            return step2(time1, time2)
                .then(time3 => [time1, time2, time3]);
        })
        .then(times => {
            const [time1, time2, time3] = times;
            return step3(time1, time2, time3);
        })
        .then(result => {
            console.log(`result is ${result}`);
            console.timeEnd("doIt");
        });
}

doIt();
Copy the code

So you can see that with promise, passing parameters is very cumbersome

In the following example, specify how many milliseconds to output a value.

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

async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value)
}

asyncPrint('hello world', 50);
Copy the code

Pay attention to

Await the Promise object after the await command, and the result may be rejected, so it is better to await the await command in the try… Add the catch callback to the catch block, or to the Promise after await

await read('1.txt'.'utf8').catch(function(err){
    console.log(err);
})
Copy the code

Await can only be used in async functions and an error will be reported if used in normal functions

async function dbFuc(db) {
  letdocs = [{}, {}, {}]; / / error docs. ForEach (function (doc) {
    await db.post(doc);
  });
}
Copy the code

The above code will report an error because await is used in normal functions. However, if you change the argument of forEach to async, there are problems

async function dbFuc(db) {
  letdocs = [{}, {}, {}]; ForEach (async) may get an error result docsfunction (doc) {
    await db.post(doc);
  });
}
Copy the code

The above code may not work because the three db.POST operations will be executed concurrently, that is, at the same time, rather than secondarily. The correct way to write this is to use the for loop.

async function dbFuc(db) {
  let docs = [{}, {}, {}];
  for (letdoc of docs) { await db.post(doc); }}Copy the code

If you really want multiple requests to execute concurrently, you can use the promise.all method.

async function dbFuc(db) {
  let docs = [{}, {}, {}];
  let promises = docs.map((doc) => db.post(doc));

  letresults = await Promise.all(promises); console.log(results); } // or use async as followsfunction dbFuc(db) {
  let docs = [{}, {}, {}];
  let promises = docs.map((doc) => db.post(doc));

  let results = [];
  for (let promise of promises) {
    results.push(await promise);
  }
  console.log(results);
}

Copy the code

conclusion

With async/await, along with promise, you can improve code simplicity and readability by writing code that looks like synchronization to handle asynchronous processes.

Advantages of Async Await: 1, solve the problem of callback hell 2, support concurrent execution 3, can add the return value return XXX; 4. You can add try/catch to your code to catch errors

References 1, segmentfault.com/a/119000000…

2, www.ruanyifeng.com/blog/2015/0…