Promise 是在 JavaScript ES6 版本開始出現的新特性,Promise 可以提供非同步流程一個錯誤處理機制。如果有好幾件非同步的工作,每一件都要依賴前一件工作的結果,又必須按照順序完成,就會變成很可怕的Callback Hell(像下面這張圖):
使用Promise結構可以簡化成這樣,可讀性高很多:
a()
.then(b)
.then(c)
.then(d)
.then(e)
.then(f)
.catch() // Error Handling
在講解Promise之前要先說明同步、非同步工作的差別。
單從字面上的意思來看,很容易以為同步是同時起步,非同步是不同時起步。其實完全不是這樣,「步」可以想像成「步道」,也就是說同步是每個工作都在同一個步道,每個工作都要等前一個工作做完才能執行:非同步是每個工作都各自在不同步道執行。
如果每個工作都很快結束那倒還好,但是 JavaScript 常被用來處理遠端網頁請求這種需要時間等待的作業,於是非同步作業的處理就變得相當重要。
聽到Promise下意識應該都會想到英文的「承諾」,這邊舉一個例子簡單說明Promise的概念:
我和公司承諾我每天都會去上班,絕對不會缺席。但是今天早上我不小心睡過頭,眼看已經快遲到了,現在有兩個選項:
把這個情境用 Promise 的方法來看,我跟公司的承諾就是 new Promise ,搭到計程車就是 resolve,搭公車就是 reject。
而搭到計程車表示成功,then 後就是準時打卡開始工作;搭到公車代表失敗,catch 後就是遲到被主管抓到罵到臭頭。不管是搭計程車還是搭公車我都還是要工作,只是過程的差別而已。
new Promise(function(resolve, reject) {
resolve(); // 正確完成的回傳方法
reject(); // 失敗的回傳方法
});
let GetInTaxi = false;
let p = new Promise(function(resolve,reject){
if (GetInTaxi){
console.log("Go to work on time.");
resolve();
}else{
console.log("Can't get in taxi.");
reject();
}
});
p.then(function() {console.log("promise resolved.")})
.catch(function() {console.log("promise rejected.")});
先宣告一個參數(GetInTaxi),然後把參數的值設定為 false 觀察 promise reject 的結果。實務上 false 的值不能人工去指定,要等前一個工作完成的回傳結果或是在執行遠端資料回傳的結果自動代入值。當 GetInTaxi 參數值為 True 的執行結果: