AsyncAwait使⽤场景
前⾔:⼀般我们都⽤await去等待⼀个async函数完成,不过按语法说明,await 等待的是⼀个表达式,这个表达式的计算结果是 Promise 对象或者其它值,所以,await后⾯实际可以接收普通函数调⽤或者直接量。
async 函数的实现
前⾯⼀篇⽂章详细介绍了Async函数,点击回顾上期内容:。
/
/ async 函数的实现,就是将 Generator 函数和⾃动执⾏器,包装在⼀个函数⾥。
async function fn(args){
// ...
}
// 等同于
function fn(args){
return spawn(function*() {
// ...
});
}
async 函数的⽤法
同 Generator 函数⼀样,async 函数返回⼀个 Promise 对象,可以使⽤ then ⽅法添加回调函数。当函数执⾏的时候,⼀旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执⾏函数体内后⾯的语句。
// ⽴即返回⼀个Promise对象
async function getStockPriceByName(name) {
var symbol = await getStockSymbol(name);
var stockPrice = await getStockPrice(symbol);
return stockPrice;
}
getStockPriceByName('goog').then(function (result){
console.log(result);
});
// 指定多少毫秒后输出⼀个值。
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value)
}
asyncPrint('hello world', 100);
/
/ 100毫秒以后,输出"hello world"
Async Await使⽤场景
当需要⽤到promise链式调⽤的时候,就体现出Async Await的优势;
有这么⼀个业务需要分步完成,每个步骤都是异步的,⽽且依赖上⼀步的执⾏结果,甚⾄依赖之前每⼀步的结果,就可以使⽤Async Await 来完成。
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();
promise版本,将使得参数传递变得⾮常⿇烦。await和async使用方法
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();
await 命令后⾯的 Promise 对象,运⾏结果可能是 rejected,所以最好把 await 命令放在 atch 代码块中,或者await后的Promise 添加catch回调。
await read('1.txt','utf8').catch(function(err){
console.log(err);
})
await 只能出现在 async 函数中,如果⽤在普通函数,就会报错。
async function dbFuc(db) {
let docs = [{}, {}, {}];
// 报错
docs.forEach(function (doc) {
await db.post(doc);
});
}
上⾯代码会报错,因为 await ⽤在普通函数之中了。但是,如果将 forEach ⽅法的参数改成 async 函数,也有问题。
async function dbFuc(db) {
let docs = [{}, {}, {}];
// 可能得到错误结果
docs.forEach(async function (doc) {
await db.post(doc);
});
}
上⾯代码可能不会正常⼯作,原因是这时三个 db.post 操作将是并发执⾏,也就是同时执⾏,⽽不是继发执⾏。正确的写法是采⽤ for 循环。
async function dbFuc(db) {
let docs = [{}, {}, {}];
for (let doc of docs) {
await db.post(doc);
}
}
如果确实希望多个请求并发执⾏,可以使⽤ Promise.all ⽅法。
async function dbFuc(db) {
let docs = [{}, {}, {}];
let promises = docs.map((doc) => db.post(doc));
let results = await Promise.all(promises);
console.log(results);
}
// 或者使⽤下⾯的写法
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);
}
总的来说,async函数有以下⼏点好处
解决了回调地狱的问题
⽀持并发执⾏
可以添加返回值 return xxx
可以在代码中添加try/catch捕获错误
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论