preface

The content of the article may not be comprehensive, but it is a lot to read slowly. I spent a long time organizing and sharing my thoughts, hoping to help you. However, there will inevitably be typing mistakes or misunderstanding points. If you find them, please tell me [email protected] by email. I will timely modify them.

Teasing & boasting

With asynchronous processing, ES5’s callback sent us into hell, ES6’s Promise got us out of the dark, and finally ES7’s async-await brought us into the light. Today we are going to learn async-await. Get on the

Async-await and Promise relationship

With async-await and promise, is it necessary to learn? With async await superior to promise, the geese are also confused after seeing such information. It turns out that async-await is the syntactic sugar of promise and generator. This is just to make our code more fluid when we write it, but also to make it more readable. Simply put: Async-await is built on top of promise and does not replace it. Understand??

Start with the basics

async function func() {
    let result = await Math.random();
    console.log(result); } func(); <! Promise:{<resolved>: undefined} __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: undefinedCopy the code

The above is the basic usage syntax of async-await. There are two unfamiliar keywords async, await, and the result of the function execution seems to return a promise object.

async

Async is used to indicate that a function is asynchronous. The return value of the defined async function is a Promise object, and callbacks can be added using the then method.


async function func1() {
    return 123;
}

func1().then(val= > {
    console.log(val); / / 123
});
 <! If async defines a function that returns a value, return 123; Resolve (123), and return without a declarative is the same as executing promise.resolve (); -->
Copy the code

await

Await can be understood as short for async wait. Await must appear inside async functions and cannot be used alone. The current function must use async modifier as long as it uses await in the function

function notAsyncFunc() {  
    await Math.random();
}
notAsyncFunc();
<! -- Uncaught SyntaxError: Unexpected identifier Uncaught SyntaxError: await only valid in asynchronous functions -->
Copy the code

Await can be followed by any JS expression. While “await” can wait for many types of things, its main purpose is to wait for the state of a Promise object to be resolved. If await is a promise object, the asynchronous function will stop executing and wait for the promise, or execute immediately if await is a normal expression.

function sleep(second) {
    return new Promise((resolve, reject) = > {
        setTimeout((a)= > {
            resolve(' enough sleep~'); }, second); })}function normalFunc() {
    console.log('normalFunc');
}
async function awaitDemo() {
    await normalFunc();
    console.log('something, ~~');
    let result = await sleep(2000);
    console.log(result);// It will be printed in two seconds} awaitDemo(); <! Vm899:9 normalFunc vm899:13 something, ~~ Promise: {<pending>} __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: undefined VM889:15 enough sleep~Copy the code

Hope to take this small chestnut, to help you understand the above.

Let’s give it a real example

In real development, you have three requests that need to happen, and the third request is a deconstruction that depends on the result of the second request.

With ES5 there are three layers of callbacks, and with Promise there are at least three THEN’s. One is horizontal code growth, the other is vertical code growth. We are going to implement async-await

// We still use setTimeout to simulate asynchronous requests
function sleep(second, param) {
    return new Promise((resolve, reject) = > {
        setTimeout((a)= >{ resolve(param); }, second); })}async function test() {
   let result1 = await sleep(2000.'req01');
	console.log(` ${result1}`);
    let result2 = await sleep(1000.'req02' + result1);
	console.log(`  ${result2}`);
    let result3 = await sleep(500.'req03' + result2);
    console.log(` ${result3}`); } test(); <! __proto__: Promise [[PromiseStatus]]: "resolved" [[PromiseValue]]: undefined VM913:14 req01 req02req01 req03req02req01 -->Copy the code

Reject processing

This is resolved, reject

function sleep(second) {
    return new Promise((resolve, reject) = > {
        setTimeout((a)= > {
            reject('want to sleep~'); }, second); })}async function errorDemo() {
    let result = await sleep(1000);
    console.log(result);
}
errorDemo();// VM706:11 Uncaught (in promise) want to sleep~

// To handle promise. reject we should wrap the block in a try catch
async function errorDemoSuper() {
    try {
        let result = await sleep(1000);
        console.log(result);
    } catch (err) {
        console.log(err);
    }
}

errorDemoSuper();// want to sleep~
// With a try catch we can get the promise. reject data back.
Copy the code

High energy ahead (parallel processing) attention please!!

For beginners who accidentally turn concurrent Ajax requests into blocking synchronous operations, I wrote exactly this code at work. The await will stop if the promise is awaited. In real services, I have three asynchronous requests to send, which are unrelated to each other. The loading of the interface needs to be cleared after all the requests are completed. Just finished learning async await

function sleep(second) {
    return new Promise((resolve, reject) = > {
        setTimeout((a)= > {
            resolve('request done! ' + Math.random()); }, second); })}async function bugDemo() {
    await sleep(1000);
    await sleep(1000);
    await sleep(1000);
    console.log('clear the loading~');
}

bugDemo(); Clear the loading~

Copy the code

Loading does wait for all requests to finish. However, you should carefully observe that the timeline request of the browser is sent after the completion of another one (please send a real Ajax request if you observe the effect).

So, what is the normal processing?

async function correctDemo() {
    let p1 = sleep(1000);
    let p2 = sleep(1000);
    let p3 = sleep(1000);
    await Promise.all([p1, p2, p3]);
    console.log('clear the loading~');
}
correctDemo();// clear the loading~
Copy the code

Well, perfect. See, async await doesn’t replace promise

Await in for loop

Await must be in the context of async functions,await is only valid in asynchronous functions.

// Normal for loop
async function forDemo() {
    let arr = [1.2.3.4.5];
    for (let i = 0; i < arr.length; i ++) {
        await arr[i];
    }
}
forDemo();// Normal output
// Because I wanted to show off, I wrote the for loop like this (however)
async function forBugDemo() {
    let arr = [1.2.3.4.5];
    arr.forEach(item= > {
        await item;
    });
}
forBugDemo();// Uncaught SyntaxError: Unexpected identifier
----------------------
async function forBugDemo() {
    let arr = [1.2.3.4.5];
    arr.forEach(async (item) => { 
        await item; 
    }); // Then no error will be reported, but asynchro after await will not wait because the underlying forEach is a while loop
}
forBugDemo();


Copy the code

hahaha

New “syntactic sugar” in ES7: async await

  • The current function must use async modifier as long as it uses await in the function
  • Async decorates a function that returns an instance of a Promise
  • Await can be understood as modifying an asynchronous operation to a synchronous effect (but it is still asynchronous)

No matter how long the night, the day will come