20. async
大约 2 分钟
async
为了使得异步操作更加的简便,ES8标准引入了async函数,async函数是Generator函数的语法糖,基本是模仿Generator函数并作出了一些改变
20.1 async与Generator的区别
有了内置执行器,Generator函数的执行必须靠执行器,而async函数自带执行器。也就是说,async函数的执行,与普通函数一样,只要一行就能执行所以过程
async的语义比Generator的语义更加的清楚,**命名与使用async函数需要用到asyuc和await关键字,**相对于Generator函数的*和yield更加让人理解,async表示函数内部有异步操作,而await表示在await后面的表达式需要等待结果
yeild后面可以是任何数据类型,而正常情况下,await后面是一个Promise对象,如果并没有手动设置一个Promise对象,而后面的表达式会被转成一个立即成功(await后面上面都不写也会传undefined)的Promise对象
async后的所有能返回值的结果都是Promise
所以,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await就是内部then()方法的语法糖
20.2 async与Generator函数的应用对比
- Generator
var fn = function (time) {
console.log("开始处理异步");
setTimeout(function () {
console.log(time);
console.log("异步处理完成");
iter.next();
}, time);
};
function* g(){
console.log("start");
yield fn(3000)
yield fn(500)
yield fn(1000)
console.log("end");
}
let iter = g();
iter.next();
- async
var fn = function (time) {
return new Promise(function (resolve, reject) {
console.log("开始处理异步");
setTimeout(function () {
resolve();
console.log(time);
console.log("异步处理完成");
}, time);
})
};
var start = async function () {
// 在这里使用起来就像同步代码那样直观
console.log('start');
await fn(3000);
await fn(500);
await fn(1000);
console.log('end');
};
start();
注意:
如果await后面的异步操作出错,那么等同于async函数返回的Promise对象直接失败,并且会将错误对象作为参数传递给then()方法的第二个函数或者catch()方法回调函数中
async function f() {
await new Promise(function (success, rejected) {
throw new Error('error');
});
}
f().then(function(value){
console.log(value)
}).catch(function(err){
console.log(err)//Error:error
});
//用try...catch来捕捉
async function f() {
try {
await new Promise(function(success, rejected) {
throw new Error("error");
});
} catch (err) {
console.log(err);
}
return await "hello world";
}
f().then(function(data) {
console.log(data);
});
//如果有多个await命令,可以统一放在try...catch结构中。
async function main() {
try {
var val1 = await firstStep();
var val2 = await secondStep(val1);
var val3 = await thirdStep(val1, val2);
console.log('Final: ', val3);
}
catch (err) {
console.error(err);
}
}