一、前言
在上一篇文章中我记录了 generator 的用法:es 异步流程(二)之generator篇
不了解generator语法的话,建议先看懂generator再看async。
generator和自动化执行器的配合已经使得异步编程非常地简洁了,但是还会有人觉得:“generator函数语义还不够直观,每次调用都需要用一次 执行器函数...”。
后来,在es2017中便出现了async/await 规范。async / await 并不是全新的东西,它只是generator的语法糖,它的底层依然是使用generator 和 promise 。
二、使用
1. async 函数格式
与generator函数使用 " * " 不同,async 函数 使用 " async "来表示该函数是异步操作函数,语义相比" * "直观很多。
async function asyncFn(){
...
}
另外,async函数的返回值是 Promise 。
async function asyncFn(){
var r1 = 100;
var r2 = 200;
return r1 + r2;
}
asyncFn().then((res)=>{
console.log(res); //输出:300
})
2. await
async 函数是内置执行器的,也就是说可以省略使用 co 这些库,大大方便了使用。
await 相当于 generator 中的 yield 。但与yield使用co不同的是,await 后面可以是 promise,也可以是基本类型。
function step1(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(100);
},1000);
});
}
async function asyncFn(){
var r1 = await step1(); // promise
var r2 = await 200; //基本类型 (r2 = 200)
return r1+r2;
}
asyncFn().then((res)=>{
console.log(res); //输出:300
})
根据 await 后面的值类型可以分成三种情况:
1. 基本类型(number、string、boolean、无then对象等)
直接返回该值
2.promise对象
返回resolve的值,如果reject则结束函数,并在async函数返回的promise.catch中截获错误。
3.thenable对象(即定义有then的对象)
当作promise来处理
需要注意的是,await 只能在async函数中使用,否则会报错:
function syncFn(){
await 100; //报错:await is only valid in async function
}
有时候该错误很难发现:
async function asyncFn(){
var arr = [1,2,3,4];
arr.forEach( (element, index)=>{ //foreach语句里传入的不是一个async函数!
await element;
});
}
实际上,传入forEach中的是一个新的函数,而该函数如果不是async函数又使用await的话则报错。
让我们来改一下:
function asyncFn(){ //这里没有async了
var arr = [1,2,3,4];
arr.forEach( async (element, index)=>{ //在这里添加async
await element;
});
}
但是这个函数可能会与你想象的不一样。它不是串行执行的,因为 forEach函数 以及每个 async函数 都是独立的缘故,这些async实际是同时执行的。
3.异步应用
串行执行异步操作:
function step1(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(100);
},1000);
});
}
function step2(v=0){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(200+v);
},1000);
});
}
async function asyncFn(){
var r1 = await step1();
var r2 = await step2(r1);
return r2;
}
asyncFn().then((res)=>{
console.log(res); //输出:300
})
并行执行异步操作:
async function asyncFn(){
var r = await Promise.all([step1(),step2()]) //step1和step2函数用上面例子的
return r;
}
asyncFn().then((res)=>{
console.log(res); //输出:[100 , 200]
})