iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 18
0
自我挑戰組

學JS的心路歷程系列 第 18

學JS的心路歷程 Day18-Promise(三)

  • 分享至 

  • xImage
  •  

今天我們來說 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 時,要注意到:

  • onFulfilled 或 onRejected 不是函式時,忽略跳過。
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.all()

前面在用 Promise 時都是一次進行一個任務,但如果今天需要一次執行多個任務時,像是同時發出兩個 ajax 請求,就需要用 Promise.all()

語法如下:

Promise.all(iterable);

iterable 代表可以傳入一個陣列或字串,一般來說都會使用陣列當作引數。

Promise.all() 會將陣列中的值全部執行完後,才會接著執行下個 then 方法。這邊要注意到幾個規則:

  • 陣列索引值與執行順序無關。
  • 陣列中的值如果不是 Promise 物件,則會自動使用 Promise.resolve 方法轉換。
  • 執行過程中只要陣列其中一個值發生錯誤,會立即回傳 reject 狀態。
  • 執行完成後會回傳一個陣列值。
  • 最好每次在使用時加上錯誤處理。當然一般 Promise 也要!

讓我們來看幾個例子吧:

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.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


上一篇
學JS的心路歷程 Day17-Promise(二)
下一篇
學JS的心路歷程 Day19-閉包 closure
系列文
學JS的心路歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言