async是generator函数的语法糖。
async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
//generator函数
var gen = function * (){
var f1 = yield readFile('xxx');
var f2 = yield readFile('xxx');
}
//async函数
var asyncRead = async function(){
var f1 = await readFile('xxx');
var f2 = await readFile('xxx');
}
async函数内置执行器,不同于generator函数需要调用next方法,他能自动执行,输出最后结果。
async函数的返回值是Promise对象。可以用.then方法指定下一步的操作。
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value);
console.log("abc");
}
asyncPrint('hello world', 500);
// Promise{xxxx}
// hello world
// abc
async函数返回的是一个Promise对象,函数内部return语句返回的值,会成为then方法回调函数的参数。
async function f(){
return 'hello world';
}
f().then(v => console.log(v));
// hello world
如果async内部抛出错误,会导致返回的Promise对象变为reject状态,这时错误会被catch方法回调函数接收到。
await命令
正常情况下,await命令后面是一个Promise对象,如果不是,会被转成一个立即resolve的Promise对象。
只要一个await语句后面的Promise变为reject,那么整个async函数都会中断执行。如果不希望第一个异步操作的失败影响函数的执行,可以将第一个await放在try…catch结构里面。或者在await后面的Promise对象再跟一个catch方法。
//try...catch...方法
async function f(){
try{
await Promise.reject('出错啦~')
}catch(e){
}
return await Promise.resolve('hello啊~')
}
//加catch方法
async function f(){
await Promise.reject('出错啦我的哥~')
.catch(e => console.log(e));
return await Promise.resolve('hello啊~')
}
因为await后面的Promise对象运行结果可能是rejected,所以最好把await命令放在try…catch代码块中。
多个await命令后面的异步操作,如果不存在继发关系最好让他们同时触发。
// 比较耗费时间和性能
let foo = await getFoo();
let bar = await getBar();
//换一种。
let [foo,bar] = await Promise.all([getFoo(),getBar()])