async/await 背後的原理其實就是Promise,但async/await 使用起來會更簡潔、更好閱讀。所以在使用之前,建議要先學好Promise的觀念~
語法
async function name(param0) {
statements
}
async function name(param0, param1) {
statements
}
async function name(param0, param1, /* …, */ paramN) {
statements
}
MDN說明:
Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
加上Async關鍵字的函式,會回傳一個Promise,即便這個值不是Promise,JavaScript也會包裝成一個Promise回傳。
範例:
async function getData(){
return 2; //設定回傳數值2
}
getData();
執行結果:
原本getData函式回傳為數值2,但加上了async關鍵字,就一定回傳一個Promise,所以數值2被包裝成一個Promise物件回傳 Promise {<fulfilled>: 2}
。
其實可以就看成這樣:
async function getData(){
return Promise.resolve(2); //直接發出成功的Promise
}
getData();
Async functions can contain zero or more await expressions. Await expressions make promise-returning functions behave as though they're synchronous by suspending execution until the returned promise is fulfilled or rejected.
意思是加上async關鍵字的函式,裡面可以有0到多個await表達式。
await會等待後方的表達式(Promise)有結果,才會繼續往下執行程式,所以看起來會像是同步的。
範例:
const myPromise = new Promise(function (resolve,reject) {
setTimeout(function () {
resolve("成功!");
}, 1000);
});
async function getData() {
let result = await myPromise;
return result;
}
getData(); //"成功!"
myPromise是一個Promise物件,JavaScript會等待await後方的myPromise有結果了,再把結果給result變數,所以呼叫getData會拿到resolve的結果。
MDN:
Use of async and await enables the use of ordinary try / catch blocks around asynchronous code.
我們要先知道,try...catch只能抓到同步的錯誤!
用範例來說明,當try...catch裡面有非同步程式,會無法捕捉到錯誤:
//先建立非同步函式
function myFunction() {
setTimeout(function () {
throw new Error("非同步錯誤");
}, 2000);
}
try {
myFunction();
console.log("try區塊");
} catch (error) {
console.log(error.message);
}
console.log("try/catch區塊之外");
執行結果:
剛剛說到try...catch無法捕捉非同步的錯誤,怎麼又說搭配一起??
這是因為await關鍵字會使Promise變為同步的執行結果,所以try...catch就可以正常執行。
來改寫之前的範例:
const myPromise = new Promise(function (resolve, reject) {
setTimeout(function () {
reject("錯誤!");
}, 1000);
});
async function getData() {
try {
let result = await myPromise;
console.log(result);
return result;
} catch (error) {
console.log(error);
return "有錯誤!";
}
}
getData(); //"有錯誤!"
以上看到async/await中,try...catch可以直接捕捉到Promise的錯誤,就不需要使用then()或catch()。
Promise則無法使用try...catch捕捉錯誤,必須搭配then()和catch()。
const myPromise = new Promise(function (resolve, reject) {
setTimeout(function () {
reject("錯誤!");
}, 1000);
});
try {
console.log("try");
myPromise
.then(function(result) {
console.log(result);
})
.catch(function(error){
console.log("Promise 錯誤捕捉:", error); // 錯誤在這裡抓到
});
} catch (error) {
console.log("無法捕捉到這個錯誤"); // 這裡永遠不會被執行
}
console.log(123);
以上分享~謝謝
MDN - async function
MDN - await
JS 原力覺醒 Day16 - Async / Await:Promise 語法糖
[Javascript] ES7 Async Await 聖經