聊聊 Promise 你不會注意的點

前言

前一篇文章梳理了promise的基礎聊聊promise系列(基礎)promise

這篇文章將從容易出現錯誤的幾種用法出發,得出如何去正確的用promise。bash

如何避免promise的回調地獄

想必你們在項目中會見過這樣的寫法。函數

const p1 = new promise((resolve, reject) => {
    resolve(true);
})
p1.then((res) => {
    if(res) {
        const p2 = new promise((resolve, reject) => {
            resolve(true);
        })
        p2.then((res) => {
            const p3 = new promise((resolve, reject) => {
                resolve(true);
            })
        })
    }
})
複製代碼

這個寫法寫出了回調地獄的感受。那如何優化他呢!!post

const p1 = new promise((resolve, reject) => {
    resolve(true);
})
const p2 = new promise((resolve, reject) => {
    resolve(true);
})
const p3 = new promise((resolve, reject) => {
    resolve(true);
})
p1.then((res) => {
    if(res) {
        return p2
    }
}).then((res) => {
    if(res) {
        return p3
    }
})
複製代碼

用這種鏈式調用的方式仍是十分的優雅的。優化

catch() 與 then(null, ...) 並不是徹底等價

舉個等價的例子:ui

Promise.reject('error').catch((res) => {
    console.log(res);
})
Promise.reject('error').then(null, (res) => {
    console.log(res);
})
複製代碼

catch是用then(null, ...)來實現的,可是在某些條件下,並非等價的,好比如下例子:spa

const p1 = new Promise((resolve, reject) => {
    if(/*正確的條件*/) {
        resolve('success');
    } else {
        reject('false');
    }
});
//用法一:
p1.then((res) => {
    console.log(res);
    throw new Error('我在then出錯了');
}, (res) => {
    console.log(res);
});
//用法二:
p1.then((res) => {
    console.log(res);
    throw new Error('我在then出錯了');
}).catch((res) => {
    console.log(res);
})
複製代碼
上述例子的區別就在與,catch能夠捕捉then中發生的錯誤,可是then的第二個回調函數捕捉不了第一個參數中的報錯。
複製代碼

輸出的結果:3d

避免promise穿透問題

什麼是promise穿透問題呢?舉個例子:code

Promise.resolve('foo').then(Promise.resolve('bar')).then(function (result) {
  console.log(result);
});
複製代碼

這個鬼東西會輸出啥??cdn

斟酌良久,你可能回答bar,那你就錯了,實際輸出的是foo。

由於then中但願得到的是一個函數。而當你傳入一個promise的時候,至關於then(null),不管你添加多少個then(null),promise都會穿透到下一個。

固然,對於上述例子,你可能但願的是這樣作:

Promise.resolve('foo').then(() => {
    return Promise.resolve('bar');
}).then(function (result) {
  console.log(result);
});
複製代碼

切記,必定要往then裏面傳入函數

幾種不一樣的寫法帶來的後果

接下來,咱們經過一個例子,來看一下不一樣寫法帶來的後果。

const func = function(last, num) {
  return new Promise((resolve, reject)=>{
      console.log(last, num);
      resolve(num);
  });
};

// 寫法一
Promise.resolve()
  .then((last)=>{return func(last, 1);})
  .then((last)=>{return func(last, 2);})
  .then((last)=>{return func(last, 3);});

// 寫法二
Promise.resolve()
  .then((last)=>{func(last, 1);})
  .then((last)=>{func(last, 2);})
  .then((last)=>{func(last, 3);});
  
 // 寫法三
Promise.resolve()
  .then(func(undefined, 1))
  .then(func(undefined, 2))
  .then(func(undefined, 3));
  
 // 寫法四
func(undefined, 1).then(func(undefined, 2)).then(func(undefined, 3));
複製代碼
  • 寫法一

結果:

undefined 1
1 2
2 3
複製代碼

這是咱們想要的結果,也是promise鏈式調用正確的寫法。

  • 寫法二 結果:
undefined 1
undefined 2
undefined 3
複製代碼

雖然在then中執行了函數,可是並無return有結果的promise給下一個then,因此後面的then永遠是收不到結果值的。

  • 寫法三

結果:

undefined 1
undefined 2
undefined 3
複製代碼

這種寫法是形成promise穿透引發的。then裏面須要是一個函數,可是卻傳了一個promise進去。

  • 寫法四

結果:

undefined 1
undefined 2
undefined 3
複製代碼

和第三種也發一致,也是promise穿透,then裏面須要是一個函數,可是卻傳了一個promise進去。

相關文章
相關標籤/搜索