前一篇文章梳理了promise的基礎聊聊promise系列(基礎)promise
這篇文章將從容易出現錯誤的幾種用法出發,得出如何去正確的用promise。bash
想必你們在項目中會見過這樣的寫法。函數
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
}
})
複製代碼
用這種鏈式調用的方式仍是十分的優雅的。優化
舉個等價的例子: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穿透問題呢?舉個例子: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進去。