1. 程式人生 > >Promise.then(a, b)與Promise.then(a).catch(b)問題詳解

Promise.then(a, b)與Promise.then(a).catch(b)問題詳解

原文: When is .then(success, fail) considered an antipattern for promises?

問題

我在bluebrid promise FAQ上面看到, 在那裡講到.then(sucess, fail)是一個antipattern. 我不能理解他關於trycatch的解釋. 下面這個例子有什麼錯誤.

some_promise.call()
.then(function(res) {logger.log(res), function(err) {logger.log(err)}})

這好像表示出, 下面才是正確的使用方式.

some_promise_call()
.then(function(res) {logger.log(res)})
.catch(function(err) {logger.log(err)})

這兩個例子有什麼不同?

解答

他們有什麼不同

這個.then()會返回一個promise, 這個promise,以防在回撥函式中出現的錯誤. 以便進行rejected的執行. 這意味著, 當你成功的logger執行的過程中, 發生了錯誤, 這個錯誤就會通過下一個.catch中的回撥函式捕獲, 但是沒有辦法在sucess後面的fail回撥函式所捕獲.

下面是一張控制流程圖:

圖片

在同步程式碼中展示:

// some_promise_call().then(looger.log, looger.log)
then: {
  try {
    var resluts = some_call()
  } catch(e) {
    logger.log(e)
    break then;
  }
  // else
  looger.log(resluts)
}

第二個log(就像是在.then中的第一個引數), 只有在沒有異常發生的時候執行. 這種塊級執行和break語法看起來有點奇怪. 這其實就是Python中的try-except-else(推薦閱讀).

// some_promise_call().then(logger.log).catch(logger.log)
try {
  var results = some_call()
  logger.log(results)
} catch (e) {
  logger.log(e)
}

這個catch也會捕獲來著成功logger這個函式執行中所發生的異常.

他們有非常大的不同.

我不理解他關於try和catch的解釋

分歧點就是在於你想要每一步都捕獲錯誤, 還是不喜歡在鏈式中捕獲錯誤. 一種預期就是你希望所有的錯誤都通過同一種錯誤處理, 當然, 當你使用antipattern(反模式)的時候, 錯誤在一些then的回撥中並沒有進行處理.

然而, 這種模式的確非常有用. 當你確實希望錯誤發生的時候, 只在那一步進行處理, 並且你希望做一些完全不同的錯誤處理. 也就是這個錯誤是不可恢復的. 注意, 那就是你的流程控制分支, 當然, 在某些情況下他會非常實用.

關於你這個例子的錯誤

// 詢問錯誤的例子:
some_promise_call()
.then(function(res) {logger.log(res)}), function(err) {logger.log(err}})

當你需要重複你的回撥函式的時候, 也就是catch後面繼續執行的時候, 最好這麼處理:

some_promise_call()
.catch(function(e) {
  return e // 這是完全可以的, 我們將會列印這個錯誤
})
.done(function(res) {
  logger.log(res)
})

你也可以繼續使用.finally()來處理.