今天我們來說 then
一些特殊情況以及 Promise.all()
與 Promise.race()
。
我們都知道函式作為引數傳入時,可以參照的方式傳入,也能傳入時執行拿回傳值作使用:
function useReference(cb){
console.log("useReference");
console.log(cb());
}
function useFunctionValue(val){
console.log(val);
}
function funB(){
return "funB";
}
useReference(funB);
useFunctionValue(funB());
但是在 Promise 中使用 then
時,要注意到:
function doA() {
console.log('doA start')
return new Promise(function(resolve, reject) {
console.log('doA end');
resolve(1);
})
}
function doB() {
console.log('doB');
return 10;
}
function final(value) {
console.log('final');
console.log(value);
return 0;
}
//正常函式參照寫法
doA().then(doB).then(final);
//doA start
//doA end
//doB
//final
//10
上面這個是一般我們把函式當引數傳入時的做法,那如果在傳入 doB
時就先執行了,會發生什麼事情呢?
doA().then(doB()).then(final);
//doA start
//doA end
//doB
//final
//1
在執行 then(doB())
時,雖然有說到如果不是函式便會跳過,但我們知道函式的回傳值也可以為函式,所以 JS 還是會執行它,當然最後得到的只是 doB()
的回傳值 2
。
所以 then(doB())
會繼續用 fulfilled
的狀態,帶著值 1
回傳新的 Promise 物件給下個 then 方法。
如果真的要這樣寫,可以改寫成這樣:
doA()
.then((val)=>{
})
.then(final);
前面在用 Promise 時都是一次進行一個任務,但如果今天需要一次執行多個任務時,像是同時發出兩個 ajax
請求,就需要用 Promise.all()
。
語法如下:
Promise.all(iterable);
iterable
代表可以傳入一個陣列或字串,一般來說都會使用陣列當作引數。
Promise.all()
會將陣列中的值全部執行完後,才會接著執行下個 then
方法。這邊要注意到幾個規則:
Promise.resolve
方法轉換。讓我們來看幾個例子吧:
var promise1 = 42;
var promise2 = Promise.resolve("hihi");
var promise3 = new Promise((resolve, reject) => {
setTimeout(() => resolve('Im async'), 1000)
});
Promise.all([promise1, promise2, promise3]).then((value) => {
console.log(value)
}).catch((err) => {
console.log(err.message)
});
//[42, "hihi", "Im async"]
Promise.race()
的規則跟Promise.all()
一樣,區別在於只會回傳最快完成的那個,不論最快成功或失敗。
通常用於獲取資源時有很多個地方,像是伺服器端與自己電腦端,只需要取最快回來的就好。
var promise1 = new Promise((resolve, reject) => {
setTimeout(() => resolve('delay 200'), 200)
});
var promise2 = new Promise((resolve, reject) => {
setTimeout(() => resolve('delay 1000'), 1000)
});
var promise3 = new Promise((resolve, reject) => {
setTimeout(() => resolve('delay 2000'), 2000)
});
Promise.race([promise1, promise2, promise3]).then((value) => {
console.log(value)
}).catch((err) => {
console.log(err.message)
});
//delay 200
到這邊 Promise 就告一段落了,希望大家看完後有比較了解。
如果有錯誤及來源未附上也歡迎留言指正,那麼我們明天見。
參考資料 :
你所不知道的 JS 非同步處理與效能
從Promise開始的JavaScript異步生活
MDN - Promise