Then the previous use of Generator+cojuejin.im/post/5ab513…
Here we continue to talk about the way js asynchronous processing async await (ieGenerator's Syntactic Sugar)
Async is short for "asynchronous", async is used to declare a function to be asynchronous, and await is used to wait for an asynchronous method to complete, await can only appear in the async function.
Also use the example of reading a file in the previous article, here rewritten as
let bluebird = require('bluebird');
let fs = require('fs');
let read = bluebird.promisify(fs.readFile);
// The Promise object behind the await command may be //rejected, so it's best to put the await command in the try...catch block.
async function 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 code
Async await is similar to generator in that it replaces the generator function's asterisk (*) with async and yield instead with await.
But the async function has improved the Generator function:
1、Built-in actuatorThe execution of the Generator function must depend on the executor, so the co function library is available, and the async function comes with an executor. That is, the execution of the async function is exactly the same as the normal function.
2、Better semantics:async and await, the semantics are clearer than the asterisk and yield. Async means that there is an asynchronous operation in the function, and await means that the expression immediately following it needs to wait for the result.
3、Wider applicability: co library convention, the yield command can only be followed by a Thunk function or a Promise object, and the await function of the async function can be followed by the Promise object and the value of the primitive type (numeric, string, and boolean, but this is equivalent to synchronization) operating)
The async function is a very new syntax feature, the new one is not part of ES6, but belongs to ES7. Currently, it is still in the proposal stage, but the transcoder Babel and regenerator are already supported and can be used after transcoding.
The role of async
The async function is responsible for returning a Promise object
If you return a direct quantity in the async function, async will pass this direct quantity.Promise.resolve() Packaged into a Promise object;
If the async function does not return a value, it will returnPromise.resolve(undefined)
What is await waiting for?
Generally we use await to wait for an async function to complete, but according to the syntax, await waits for an expression. The result of this expression is a Promise object or other value, so await can actually receive the normal function call or Direct quantity
If await waits for a promise object, then the result of the expression following it is what it waits for;
If it is a promise object,Await will blockThe following code, wait for the promise object resolve, get the value of resolve as the result of the await expression
Although await is blocked, await is in async,Async will not block, all its internal blocking is encapsulated in a promise object to execute asynchronously
Async Await usage scenario
As in the above example, when you need to use the promise chain call, it shows the advantages of Async Await;
Suppose a business needs to be completed step by step, each step is asynchronous, and depending on the execution result of the previous step, or even rely on the results of each previous step, you can use Async Await to complete
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 code
If you use promise to achieve
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 code
Visible with the promise, parameter transfer is very troublesome
The following example specifies 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 code
note
The Promise object behind the await command may result in a rejected result, so it's best to put the await command in the try...catch block, or add a catch callback to the Promise after await.
await read('1.txt','utf8').catch(function(err){
console.log(err);
})
Copy code
Await can only appear in the async function. If it is used in a normal function, it will report an error.
async function dbFuc(db) {
let docs = [{}, {}, {}];
// error
docs.forEach(function (doc) {
await db.post(doc);
});
}
Copy code
The above code will report an error because await is used in normal functions. However, if you change the parameters of the forEach method to the async function, there is also a problem.
async function dbFuc(db) {
let docs = [{}, {}, {}];
// may get the wrong result
docs.forEach(async function (doc) {
await db.post(doc);
});
}
Copy code
The above code may not work properly because the three db.post operations will be executed concurrently, that is, at the same time, not concurrently. The correct way to do this is to use a for loop.
async function dbFuc(db) {
let docs = [{}, {}, {}];
for (let doc of docs) {
await db.post(doc);
}
}
Copy 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));
let results = await Promise.all(promises);
console.log(results);
}
// or use the following method
async function 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 code
to sum up
Using async / await, with a promise, you can handle asynchronous processes by writing code that looks like synchronization, improving code simplicity and readability.
Advantages of Async Await: 1. Solved the problem of callback hell
2, support concurrent execution
3, you can add a return value return xxx;
4, you can add try/catch capture error in the code
Reference material
1、
2、