With the release of Node 7, more and more people are beginning to study the async/await that 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 C # 5.0 syntax. The async/await of C # 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 above the 4.0 version.
In both C # and JavaScript, Async/await is a great feature, and they are all very sweet grammatical sugars. C # async/await implementation is inseparable from Task or task<result> class, and JavaScript async/await implementation, also inseparable from Promise.
Now put aside the C # and the. NET Framework and concentrate on the async/await of JavaScript. what are async and await doing?
Any name is meaningful, first of all to understand the literal meaning. Async is shorthand for "asynchronous" and await can be considered a shorthand for async wait. So it should be very well understood async is used to declare that a function is asynchronous, and await is used to wait for an asynchronous method to execute.
There is also an interesting grammatical rule that await can only appear in the async function. Then the careful friend will have a question, if await can only appear in the Async function, that this async function should call.
If you need to call a async function via await, the outside of this call must be wrapped with a async function, and then ... Into the cycle of death, never to the end ...
If the async function does not need await to invoke, then 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 go back to the value we want directly through the return statement, but if so, there seems to be nothing await. So, write the code to try and see what it returns:
Asyncfunction 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 '}
So, the Async function returns a Promise object. This information can also be obtained from the documentation. The async function, which contains a function statement, a function expression, a lambda expression, returns a Promise object, and if you return a direct amount in a function, async encapsulates the direct amount into a Promise object by Promise.resolve ().
The async function returns a Promise object, so in the case where the outermost layer cannot get its return value with await, we should certainly use the original method: then () chain to handle the Promise object, like this
Testasync (). Then (v => {
console.log (v)); Output Hello async
});
Now look back and think about what if the async function doesn't return a value. It is easy to think that it will return to Promise.resolve (undefined).
Reminiscent of the Promise feature-no wait, so execute the async function without await, it executes immediately, returns a Promise object, and never blocks the subsequent statements. This is not the same as normal functions that return Promise objects.
So the next key point is the await keyword. What the hell are await waiting for?
Generally, it is assumed that await is waiting for a async function to complete. However, by syntax, await waits for an expression that evaluates to a Promise object or other value (in other words, there is no special qualification).
Because the async function returns a Promise object, await can be used to wait for the return value of a async function--which can be said to be await in the same async function, but to be clear, it is actually a return value. Note that await is not only used for Promise objects, it can be the result of arbitrary expressions, so await can actually be followed by ordinary function calls or direct quantities. So the following example works correctly
function getsomething () {return
"something";
}
Asyncfunction Testasync () {return
promise.resolve ("Hello async");
}
Asyncfunction Test () {
Const V1 = awaitgetsomething ();
Const V2 = Awaittestasync ();
Console.log (v1, v2);
}
Test ();
await wait until it's time to wait, and then what?
Await waits for something, a Promise object, or some other value, and then. I have to say first that await is an operator that is used to compose an expression, and the result of an await expression depends on what it waits for.
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, the await is busy, blocking the following code, waiting for the Promise object resolve, and then getting the resolve value as the result of the await expression's operation.
See the word block above, flustered it ... Rest assured, this is why await must be used in the async function. Async function calls do not cause blocking, and all of the blocking inside it is encapsulated asynchronously in a Promise object. What did async/await do for us ? make a simple comparison.
As explained above, async encapsulates the return value of a function expression or Lambda to a Promise object, and await waits for the Promise to complete and returns the result of its resolve.
Now, for example, using settimeout to simulate time-consuming asynchronous operations, 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 you switch to async/await, it would be.
function Takelongtime () {return
new Promise (resolve => {
settimeout () => Resolve ("Long_time_value"), 1000);
}
Asyncfunction Test () {
Const V = awaittakelongtime ();
Console.log (v);
}
Test ();
The eagle-eyed classmate has found that takelongtime () has not been declared as async. In fact, Takelongtime () itself is the return of the Promise object, plus async results are the same, if not understand, please go back to see the above "async what role."
Another question arises, the two pieces of code, the two ways to deal with asynchronous calls (in fact, the processing of Promise objects) is not obvious, even the use of async/await also need to write more code, that its advantages in the end. The advantage of Async/await is to deal with then chain
A single Promise chain does not discover the advantages of async/await, but when it comes to dealing with then chains of multiple Promise, the advantages can be reflected (interestingly, Promise solves the problem of multi-layer callbacks through the then chain, and now uses Asyn C/await to further optimize it).
Suppose a business is completed in multiple steps, each of which is asynchronous and dependent on the results of the previous step. We still use settimeout to simulate asynchronous operations:
/**
* Incoming parameter n, indicating the time of execution of this function (milliseconds)
* The result is n + 200, which will be used for the next step *
/function Takelongtime (n) {return
new Promise (Resolve => {
settimeout (() => resolve (n +), 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 implement the three-step process.
function DoIt () {
console.time ("doIt");
Const TIME1 =;
Step1 (time1)
. Then (time2 => Step2 (time2)). Then (Time3 => (step3
))
. Time3 (Result then {
Console.log (' result is ${result} ');
Console.timeend ("DoIt");}
);
DoIt ();
C:\var\test>node--harmony_async_await.
Step1 with +//STEP2 with//STEP3 to//is
900
//doit:1507.251ms
Output result is the STEP3 () parameter 700 + 200 = 900. The doIt () sequence performs three steps, with a total of 300 + 500 + 700 = 1500 milliseconds, consistent with the results of the Console.time ()/console.timeend () calculation.
If it was done with async/await, it would be.
Asyncfunction doIt () {
console.time ("doIt");
Const TIME1 =;
Const TIME2 = AWAITSTEP1 (time1);
Const TIME3 = AWAITSTEP2 (time2);
Const RESULT = AWAITSTEP3 (Time3);
Console.log (' result is ${result} ');
Console.timeend ("DoIt");
}
DoIt ();
The results are the same as the previous Promise implementations, but the code looks much clearer and is almost as cool as the sync code
Changing the business requirements now is still three steps, but each step requires the results 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 use async/await to write:
Asyncfunction doIt () {
console.time ("doIt");
Const TIME1 =;
Const TIME2 = AWAITSTEP1 (time1);
Const TIME3 = AWAITSTEP2 (time1, time2);
Const RESULT = AWAITSTEP3 (time1, time2, time3);
Console.log (' result is ${result} ');
Console.timeend ("DoIt");
}
DoIt ();
C:\var\test>node--harmony_async_await.
Step1 with STEP2///
step3 with 1800 = + +
+ 1000
//result is 2000
//doit:2907.387ms
Apart from feeling that the execution time is longer, it doesn't seem to be any different from the previous example. Don't worry, seriously think about what it would be like to write it in Promise way.
function DoIt () {
console.time ("doIt");
Const TIME1 =;
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 ();
There is no feeling a little complicated look. The pile of parameters to deal with, is the Promise scheme of the dead Point--parameter transmission too troublesome, look at the faint.