一、如何使用async/await
async函式是Generator的一個語法糖,使用async函式實際上返回的是一個Promise物件。如下:
async function fn(){
return 30;
}
// 或者
const fn = async () =>{
return 30;
}複製程式碼
在宣告函式的時候,前面加上關鍵字async
即可。我們可以使用 console.log
列印出上邊宣告的函式fn,結果如下:
console.log(fn());
// result
Promise = {
_proto_: Promise,
[[PromiseStatus]]: "resolved",
[[PromiseValue]]: 30
}複製程式碼
顯然,fn的執行結果其實就是一個Promise物件,因此我們可以使用then來處理後續邏輯。
fn().then(res =>{
console.log(res);
})複製程式碼
await的是含義是等待。意思是程式碼需要等待await後面的函式執行完成並且有了返回結果之後,才繼續執行後續的程式碼,以此來實現同步的效果。 需要注意的是,await
關鍵字只能在async
函式中使用,並且await
後面的函式執行後必須返回一個Promise
物件才能實現同步的效果。
當我們使用一個變數去接收await的返回值時,該返回值是Promise中resolve出來的值(也就是PromiseValue)。
// 定一個返回Promise物件的函式
function f1(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(1);
},1000);
})
}
function f2(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(2);
},1000);
})
}
function f3(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(3);
},1000);
})
}
const foo = async () =>{
const result_1 = await f1();
console.log(result_1);
const result_2 = await f2();
console.log(result_2);
const c = await f3();
console.log(result_3);
}
foo();
// 執行結果:
// 1
// 2
// 3複製程式碼
執行這個例子我們可以看出,當在async
函式中,執行遇到await
時,就會等待await
後面的函式執行完畢,而不會直接執行後續程式
二、async/await相對於直接使用Promise的優勢
如果我們直接使用Promise的話,想要實現以上的結果,就不得不把後續的邏輯寫在then方法中。
function f1(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(1);
},1000);
})
}
function f2(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(2);
},1000);
})
}
function f3(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
resolve(3);
},1000);
})
}
const foo = () =>{
return f1().then(t =>{
console.log(t);
return f2();
}).then(t =>{
console.log(t);
return f3();
}).then(t =>{
console.log(t)
});
}
foo();複製程式碼
異常處理
在Promise中,我們知道是通過catch的方式來捕獲異常。而當我們使用async時,則是通過try/catch
來捕獲異常。
function fn(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("some error.");
},1000)
})
}
const foo = asyn () =>{
try{
await fn();
}catch(e){
console.log(e); //some error.
}
}
foo();複製程式碼
如果有多個await函式,那麼只會返回第一個捕獲到的異常。
function f1(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f1 error");
},1000)
})
}
function f2(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f2 error");
},1000)
})
}
function f3(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f3 error");
},1000)
})
}
const foo = async () =>{
try{
await f1();
await f2();
await f3();
}catch(e){
console.log(e); //f1 error
}
}
foo();複製程式碼
如果我們直接使用Promise,實現以上效果,程式碼應該寫成如下:
function f1(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f1 error");
},1000)
})
}
function f2(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f2 error");
},1000)
})
}
function f3(){
return new Promise((resolve,reject) =>{
setTimeout(() =>{
reject("f3 error");
},1000)
})
}
const foo = () =>{
return f1().then(() =>{
return f2();
}).then(() =>{
return f3();
}).catch(err =>{
console.log(err);
})
}
foo();複製程式碼
很顯然,如果使用async/await的話,程式碼結構會更加簡潔,邏輯也更加清晰,更利於專案中的開發以及維護。