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. 我不能理解他關於try
和catch
的解釋. 下面這個例子有什麼錯誤.
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()
來處理.