文章出自個人博客https://knightyun.github.io/2019/08/02/js-async-await,轉載請申明
async
用於聲明異步函數,返回值爲一個 Promise
對象,它以類似同步的方法來寫異步方法,語法與聲明函數類似,例如:
async function fn() {
console.log('Hello world!');
}
console.log(fn().constructor); // Promise()
// 這裏證明其返回值爲一個 Promise 對象;
也許會有疑問,返回值是 Promise 對象,那麼函數本身定義的返回值跑到哪裏去了呢?其實,熟悉 Promise 的就知道其異步結果是通過 .then()
或者 .catch()
方法來獲取並進行進一步處理的,這樣一個道理,定義的異步函數中的返回值會當成 resolve
狀態來處理,一般用 .then()
方法處理,而如果定義的異步函數拋出錯誤,例如變量未定義,則會被當做 reject
狀態來處理,一般使用 .catch()
方法來處理;
舉例:
// 使用 .then() 的情況
async function fn1() {
return 'Hello world!';
}
fn1().then(function(res) {
console.log(res);
});
// Hello world!
// 使用 .catch() 的情況
async function fn2() {
console.log(aaa); // 這裏的變量 aaa 未定義,爲了製造錯誤
}
fn2().catch(function(error) {
console.log(error);
});
// ReferenceError: aaa is not defined
假如是既有返回值,又有錯誤的話,來看看結果如何:
async function fn3(){
console.log(aaa); // aaa 依然未定義;
return 'Hello world!';
}
fn3().then(function(res){
console.log(res);
}).catch(function(error){
console.log(error);
});
// ReferenceError: aaa is not defined
結果證明只會執行 reject
狀態的情況下的語句,忽略了 resolve
時的代碼,所以此處值得 注意;
await
用法顧名思義,有等待的意思,語法爲:
var value = await myPromise();
注意 await
必須在 async function
內使用,否則會提示語法錯誤;
這裏的 myPromise()
是一個 Promise對象,而自定義的變量 value
則用於獲取 Promise 對象返回的 resolve 狀態值,如果 await 後面跟的是其他值,則直接返回該值;
所以,所謂等待其實就是指暫停當前 async function
內部語句的執行,等待後面的 Promise
處理完返回結果後,繼續執行 async function
函數內部的剩餘語句;
舉例:
async function fn(){
console.log(1);
var result = await new Promise(function(resolve, reject){
setTimeout(function(){
resolve(2);
}, 2000);
});
console.log(result);
console.log(3);
console.log(await 4); // 4 會被直接返回
}
fn();
// 1
// 2 (2 秒後輸出)
// 3
// 4
如果 await 後面的 Promise 返回一個 reject
狀態的結果的話,則會被當成錯誤在後臺拋出,例如:
async function fn(){
console.log(1);
var result = await new Promise(function(resolve, reject){
setTimeout(function(){
reject(2);
}, 2000);
});
console.log(3);
}
fn();
// 1
// Uncaught (in promise) 2 (2 秒後輸出)
如上,2 秒後會拋出出錯誤,並且 3 這個數並沒有被輸出,說明後面的執行也被忽略了;
另外,await 後面的 Promise 返回的 reject, 也可以被該 async 函數返回的 Promise 對象以 reject 狀態獲取,例如:
async function fn(){
console.log(1);
var result = await new Promise(function(resolve, reject){
setTimeout(function(){
reject(2);
}, 2000);
});
console.log(3);
}
fn().catch(function(error){
console.log(error);
});
// 1
// 2 (2 秒後輸出)
這種情況就不會以錯誤拋出,直接對異常值進行了處理,並且最後同樣沒有輸出數字 3,即後面的代碼依然被忽略了;