参考了阮老师的ES6教程案例,加上自己的整理,总结了async...await常见用法:
async用于申明function异步,await用于等待一个异步方法执行完成
先介绍async的用法:
1、async函数返回一个 Promise 对象
//一个普通函数
function getData(){
return "syy";
}
console.log(getData()) //syy
//加上async后
async function getData(){
return "syy";
}
console.log(getData()); //Promise {<resolved>: "syy"}
2、async函数内部return语句返回的值,会成为then方法回调函数的参数
async function getData(){
return "syy";
}
getData().then(data=>{
console.log(data) //syy
});
3、async函数内部抛出错误,会导致返回的 Promise 对象变为reject状态,抛出的错误对象会被catch方法回调函数接收到
async function getData(){
throw new Error('出错了');
}
getData()
.then(v=>{
console.log(v)
})
.catch(e=>{
console.log(e) //Error: 出错了
});
async function getData() {
throw new Error('出错了');
}
getData()
.then(
v => console.log(v),
e => console.log(e) //Error: 出错了
)
4、async 函数有多种使用形式
1⃣️ async function foo() {}
2⃣️ const foo = async function () {}
const foo = async () => {}
3⃣️ let obj = { async foo() { } }
obj.foo().then(...)
开始进入async...await主题:
1、正常情况下,await命令后面是一个Promise对象。如果不是,会被转成一个立即resolve的Promise对象。
async function getData(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
var name = "syy";
resolve(name)
},1000)
})
}
async function test(){
var p = await getData();
console.log(p);
};
test(); //syy
async function f() {
return await 123;
}
f()
.then(v =>
console.log(v)
) //123
2、await命令后面的 Promise 对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收到
//上面代码中,await语句前面没有return,但是reject方法的参数依然传入了catch方法的回调函数。这里如果在await前面加上return,效果是一样的。
async function f() {
await Promise.reject('出错了');
}
f()
.then(v =>
console.log(v)
)
.catch(e =>
console.log(e)
) //出错了
3、Promise 对象的状态变化:async函数返回的 Promise 对象,必须等到内部所有await命令后面的 Promise 对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async函数内部的异步操作执行完,才会执行then方法指定的回调函数。
只要一个await语句后面的 Promise 变为reject,那么整个async函数都会中断执行
async function f() {
await Promise.reject('出错了');
await Promise.resolve('hello world'); //不会执行
} //Promise {<rejected>: "出错了"}
4、前一个异步操作失败,也不要中断后面的异步操作。这时可以将第一个await
放在try...catch
结构里面,这样不管这个异步操作是否成功,第二个await
都会执行
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f()
.then(v =>
console.log(v)
) //hello world
//另一种方法:await后面的 Promise 对象再跟一个catch方法,处理前面可能出现的错误
async function f() {
await Promise.reject('出错了')
.catch(e =>
console.log(e)
); //出错了
return await Promise.resolve('hello world');
}
f()
.then(v =>
console.log(v)
) //hello world
5、错误处理:如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject
async function f() {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
}
f()
.then(v =>
console.log(v)
)
.catch(e =>
console.log(e)
) //Error:出错了
6、多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发
let foo = await getFoo();
let bar = await getBar();
//上面代码中,getFoo和getBar是两个独立的异步操作(即互不依赖),被写成继发关系。这样比较耗时,因为只有getFoo完成以后,才会执行getBar,完全可以让它们同时触发
写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
//上面两种写法,getFoo和getBar都是同时触发,这样就会缩短程序的执行时间