本系列文章經過重新編排和擴充,已出書為ECMAScript關鍵30天。原始文章因當時準備時程緊迫,多少有些許錯誤。為了避免造成讀者的困擾,以及配合書籍的內容規劃,將會陸續更新本系列文章。
本篇文章在 2021/11/2 已更新。
ES2015 中,將 Promise 標準化,解決了以往要寫非同步時容易產生的 callback hell。不過寫久了就會發現,如果有多個非同步,或是有複雜的判斷邏輯時,Promise 的寫法還是會讓程式產生巢狀,語意上也不好解讀。
因此在 ES2017 中,最重要的特性就是新增非同步寫法的方式 - 以 Promise 結合 Generator 的特性,以await
跟async
作為非同步函式的前綴字,來簡化 Promise 的實現。
基本用法是當要宣告非同步函式時,使用async
作為函式的前綴字。當要執行函式時,使用await
作為呼叫函式的前綴字。另外在函式裡有執行到非同步的地方,也可以用await
表示這裡需要等待結果回傳。
async function allResult() {
const r1 = await fn1();
const r2 = await fn2();
return [r1, r2];
}
const result = await allResult();
跟原本的 Promise 寫法比較看看。先建立一些非同步函式 -
const downloadData() = () => {
return new Promise((resolve, reject) => {...})
}
const processData() = () => {
return new Promise((resolve, reject) => {...})
}
const ProcessError() = () => {
return new Promise((resolve, reject) => {...})
}
getData 函式回傳的 Promise 會導致 promise chaining,將函式分隔成多個部份。
function getData(params) {
return downloadData(params) // returns a promise
.then(v => {
return processData(params); // returns a promise
});
.catch(e => {
return ProcessError(params); // returns a promise
})
}
以async & await 改寫 getData 函式的話,就不會產生 promise chaining,並且可以搭配 try catch
處理意外錯誤。
async function getData(params) {
let v;
try {
v = await downloadData(params);
} catch(e) {
v = await ProcessError(params);
}
return processData(vparams);
}