談談Promise那點事(二)

找抽的小陀螺發表於2017-09-24

上篇 談談Promise那點事(一)已經談談了Promise的基礎的知識 下面來嘮嘮實際應用的誤區
上程式碼來看看 是否在平常遇到過

  • 沒有返回值
function fn () {
    return new Promise (function (resolve, reject) {
        if () {
            //操作成功
        } else {
            //操作失敗
        }
    })
}
fn().then(function(data1) {
    load(data1)
}).then(function(data2) {
    load(data2)
})複製程式碼

Promise 能夠讓我們在回撥函式中return 所以then中可以return一個Promise物件或者普通物件 這樣在在後面then的回撥中是接受不到上一個load 執行的結果 因為沒有return 現在都是undefined
所以在then中一定要return 或者throw

  • 沒有Catch
function fn () {
    return new Promise (function (resolve, reject) {
        if () {
            //操作成功
        } else {
            //操作失敗
        }
    })
}
fn().then(function(data1) {
    reuturn load(data1)
}).then(function(data2) {
    return load(data2)
}).then()複製程式碼

這裡沒有新增catch 捕獲錯誤 以至於在中間任何地方發生錯誤都查詢不到 很難排查

fn().then(function(data1) {
    reuturn load(data1)
}).then(function(data2) {
    return load(data2)
}).catch(err => console.log(err))複製程式碼

改成這樣有了catch 來捕獲錯誤在任何地方出現錯誤都會在這裡捕獲
Promise 鏈中可能出現錯誤一定新增 catch

  • catch()與then(null, fn)
    解釋下 即使有了catch 但是then return返回的是空的 這裡就捕獲到了 看下程式碼
fn().then(function(data1) {
    reuturn load1()
}).catch(err => console.log(err))複製程式碼

catch捕獲的並不是fn的錯誤,而是load1的錯誤 所以這時候就要結合用了

fn().then(function(data1) {
    reuturn load1()
}, err=>console.log(err))
.catch(err => console.log(err))複製程式碼

Promise 在有些情況下catch與then(null, fn)並不等同

  • 處理併發時候 Promise.all 靜態方法
fn().then(promiseArr=> {
        var resArr = [];
        promiseArr.forEach(v=>{
            v().then(res=> resArr.push(res))
        })
        return resArr;
}).then(ret => console.log(ret))複製程式碼

這樣寫感覺上是沒毛病的 但是有個問題 最後then 列印結果不能確保promiseArr 的Promise都能夠順利完成 所以這個時候 用Promise.all 靜態方法 在上一篇提到過這個靜態方法
這來回憶下

Promise.all(promises).then(function (posts) {
 // ...
}).catch(function(reason){
 // ...
});複製程式碼
  1. 這裡如果全部成功,狀態變為resolved,返回值將組成一個陣列傳給回撥
  2. 只要有一個失敗,狀態就變為rejected,返回值將直接傳遞給回撥
  3. 返回值也是個Promise例項
    所以演變下
fn().then(promiseArr=> {
        //var resArr = [];
        //promiseArr.forEach(v=>{
            //v().then(res=> resArr.push(res))
        //})
        //return resArr;
        return Promise.all(promiseArr);
}).then(ret => console.log(ret))複製程式碼

在長度未知情況下併發 使用Promise.all 來解決

所以說:

  • then方法中 永遠 return 或 throw

  • 如果 promise 鏈中可能出現錯誤,一定新增 catch

  • 永遠傳遞函式給 then 方法

  • 不要把 promise 寫成巢狀

參考連結 :
深入理解Promise
es6入門 阮一峰

相關文章