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.

Async-await and Promise relationship

It is common to see that with async-await, is there any need to learn promise, and async await is better than promise? After receiving these messages, we will be confused. 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.

The basic grammar



async function basicDemo() {
    let result = await Math.random();
    console.log(result);
}

basicDemo();
/ / 0.6484863241051226
//Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: undefined}Copy the code

The above code is the basic use 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 defined function returns a Promise object. Callbacks can be added using the then method.



async function demo01() {
    return 123;
}

demo01().then(val= > {
    console.log(val);/ / 123}); ifasyncThe function defined has a return value,return 123; The equivalent ofPromise.resolve(123), no declarativereturnThat's equivalent to executingPromise.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.



function notAsyncFunc() {
    await Math.random();
}
notAsyncFunc();//Uncaught SyntaxError: Unexpected identifierCopy 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();
// normalFunc
// VM4036:13 something, ~~
// VM4036:15 enough sleep~Copy the code

Hopefully through the above demo, you can understand what I said above.

The instance

For example, you have three requests that need to happen, and the third request depends on the deconstruction of the second request and the second request depends on the result of the first 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. Implementation of 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');
    let result2 = await sleep(1000.'req02' + result1);
    let result3 = await sleep(500.'req03' + result2);
    console.log(`
        ${result3}
        ${result2}
        ${result1}
    `);
}

test();
//req03req02req01
//req02req01
//req01Copy the code

Error handling

All this code seems to say resolve, reject. What do we do?



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

Be careful with your parallelism!!

Why did I add three exclamation points here? I wrote this code at work because it would be a beginner’s mistake to send concurrent Ajax requests as blocking synchronization. The await will stop if the promise is awaited. The service is as follows: I have three asynchronous requests to send, which are unrelated to each other. I just need to clear the loading of the interface when all the requests are finished. 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();Copy the code

Loading does wait for all requests to finish. However, if you carefully observe the browser timeline request, one is finished and then another is sent (if you observe the effect, please send a real Ajax request), then 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

Yeah, perfect. See ~ async-await doesn’t replace promise.

Await in for loop

Finally, await must be in the context of async function.



// 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 want to show off, WRITE the for loop like this
async function forBugDemo() {
    let arr = [1.2.3.4.5];
    arr.forEach(item= > {
        await item;
    });
}
forBugDemo();// Uncaught SyntaxError: Unexpected identifierCopy the code

refs

I don’t know if I got my message across. Here are some excellent articles. ES7 Async Await bible Understanding JavaScript’s async Await