Understand the async/await of JavaScript

Source: Internet
Author: User

With the release of Node 7, more and more people are beginning to study async/await, which is said to be an end-level solution for asynchronous programming. The first time I saw this group of keywords was not in the JavaScript language, but in the syntax of C # 5.0. C # async/await needs to be used in more than 4.5 versions of the. NET Framework, so I'm sad for a while--in order to be compatible with XP systems, the software we develop cannot use the. NET Framework that is higher than the 4.0 version.

I talked about this earlier in the chat asynchronous invocation of flattened. Whether in C # or JavaScript, Async/await is a great feature, and they are all very sweet syntax sugars. C # async/await implementation can not be separated from the Task or task\<result\> class, and JavaScript async/await implementation, also inseparable from Promise.

Now throw away the C # and. NET Framework and focus on the async/await of JavaScript.

What async and await are doing

Any name is meaningful and is first understood by the literal meaning. Async is shorthand for "async," and an await can be thought of as a shorthand for async wait. So it should be good to understand that async is used to assert that a function is asynchronous, while await waits for an asynchronous method to execute.

There is also a very interesting grammatical rule that await can only appear in the async function. Then the attentive friend raises a question, if the await can only appear in the Async function, how should this async function be called?

If you need to invoke an async function through await, then the outside of this call must be wrapped in an async function, and then ... Into the cycle of death, never doomed ...

If the async function doesn't need an await to invoke, what does async do?

What role does async play?

The key to this problem is how the Async function handles its return value!

We certainly want it to return the return value we want directly through the statement, but if that's the case, there seems to be nothing to await. So, write a piece of code to try and see what it will return:

async function testAsync() {    return "hello async";}const result = testAsync();console.log(result);

Seeing the output is an epiphany-the output is a Promise object.

c:\var\test> node --harmony_async_await .Promise { ‘hello async‘ }

Therefore, the Async function returns a Promise object. This information can also be obtained from the documentation. The Async function (which contains function statements, function expressions, lambda expressions) returns a Promise object, and if a direct amount is in the function return , async will encapsulate the direct amount Promise.resolve() into a Promise object.

The async function returns a Promise object, so in the case where the outermost layer cannot get its return value with await, we should of course use the same method: then() chain to handle the Promise object, just like this

testAsync().then(v => {    console.log(v);    // 输出 hello async});

Now look back and think, what if the async function doesn't return a value? It is easy to think that it will return Promise.resolve(undefined) .

Lenovo Promise Features-no wait, so without await the execution of an async function, it executes immediately, returns a Promise object, and never blocks the subsequent statement. This is not the same as the normal return Promise object function.

So the next key point is the await keyword.

What's waiting for await?

In general, it is assumed that await is waiting for an async function to complete. However, as the syntax suggests, await is an expression that evaluates to a Promise object or other value (in other words, no special qualification).

Because the async function returns a Promise object, await can be used to wait for the return value of an async function-which can be said to await an async function, but it is clear that it is actually a return value. Notice that await is not only used for Promise objects, it can wait for the result of any expression, so an await can be followed by an ordinary function call or a direct amount. So the following example works perfectly correctly

function getSomething() {    return "something";}async function testAsync() {    return Promise.resolve("hello async");}async function test() {    const v1 = await getSomething();    const v2 = await testAsync();    console.log(v1, v2);}test();
Await wait, then what?

Await wait for what it waits for, a Promise object, or other value, then? I have to say first, it await 's an operator that's used to make up an expression, and the result of an await expression depends on what it's doing.

If it waits for a Promise object, the result of the await expression is what it waits for.

If it waits for a Promise object, await is busy, it blocks the code behind, waits for the Promise object to resolve, and then gets the value of resolve as the result of the await expression.

See above the blocking word, flustered ... Rest assured, this is why await must be used in the async function. Async function calls do not cause blocking, and all of its internal blocking is encapsulated in an Promise object that executes asynchronously.

What did async/await do to help us make a simple comparison?

As explained above, async encapsulates the return value of the subsequent function (function expression or LAMBDA) into a Promise object, while await waits for the Promise to complete and returns the result of its resolve.

Now for example, with setTimeout a simulated time-consuming asynchronous operation, let's take a look at how to write without async/await.

function takeLongTime() {    return new Promise(resolve => {        setTimeout(() => resolve("long_time_value"), 1000);    });}takeLongTime().then(v => {    console.log("got", v);});

If we switch to async/await, this will be it.

function takeLongTime() {    return new Promise(resolve => {        setTimeout(() => resolve("long_time_value"), 1000);    });}async function test() {    const v = await takeLongTime();    console.log(v);}test();

Sharp-eyed's classmates have found takeLongTime() no statement for async . In fact, takeLongTime() itself is the return of the Promise object, add no async results are the same, if not understand, go back and look at the above "async what role".

Another question arises, these two pieces of code, two ways to the asynchronous invocation of processing (in fact, the processing of Promise objects) is not obvious difference, even the use of async/await also need to write some code, then its advantages in the end?

The advantage of async/await is to handle then chain

A single Promise chain does not discover the advantages of async/await, but when it comes to dealing with the then chain consisting of multiple Promise, the advantages can be reflected (it is interesting that Promise through then chain to solve the problem of multi-layered callbacks, and now with Asyn C/await to further optimize it).

Suppose a business is completed in multiple steps, each step is asynchronous, and depends on the result of the previous step. We still use it setTimeout to simulate asynchronous operations:

/** * 传入参数 n,表示这个函数执行的时间(毫秒) * 执行的结果是 n + 200,这个值将用于下一步骤 */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(n) {    console.log(`step2 with ${n}`);    return takeLongTime(n);}function step3(n) {    console.log(`step3 with ${n}`);    return takeLongTime(n);}

Now use the Promise method to achieve these three steps of processing

function doIt() {    console.time("doIt");    const time1 = 300;    step1(time1)        .then(time2 => step2(time2))        .then(time3 => step3(time3))        .then(result => {            console.log(`result is ${result}`);            console.timeEnd("doIt");        });}doIt();// c:\var\test>node --harmony_async_await .// step1 with 300// step2 with 500// step3 with 700// result is 900// doIt: 1507.251ms

The output result is step3() the parameter 700 + 200 = 900 . The doIt() sequence performed three steps, with a total 300 + 500 + 700 = 1500 of milliseconds, console.time()/console.timeEnd() consistent with the computed results.

If it was done with async/await, it would be.

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

The result is the same as the previous Promise implementation, but the code looks much clearer, almost like synchronous code

and the cooler one.

It is still three steps to change the business requirements, but each step requires the results of each of the previous steps.

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);}

This time first write with async/await:

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();// c:\var\test>node --harmony_async_await .// step1 with 300// step2 with 800 = 300 + 500// step3 with 1800 = 300 + 500 + 1000// result is 2000// doIt: 2907.387ms

In addition to feeling that the execution time has become longer, it seems to be no different from the previous example! Don't worry, think about what it would look like if it were written in Promise way.

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();

Did you feel a little complicated? That heap of parameter processing, is the dead point of the Promise scheme-the parameter transfer is too troublesome, look at the faint!

Wash and sleep.

For now, have you understood async/await? But in fact there are some things not mentioned--promise may reject Ah, how to deal with it? What if you need to process 3 steps in parallel and wait for all the results?

Nanyi The teacher has said, I would not bother to say.

Understand the async/await of JavaScript

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.