2015-02-17 61 views
7

我不一定要錯誤,但我有:我可以早點用藍鳥諾言斷開一條鏈嗎?

getFromDb().then (tradeData) -> 
    if not tradeData 
    # DO NOT CONTINUE THE CHAIN 
    else 
    getLatestPrice tradeData 
.then (latestPrice) -> 
    ... 
.then -> 
    ... 
.then -> 
    ... 
.catch (err) -> 
    next err 

有我的方式來終止鏈,如果沒有tradeData?

+0

你不能明確地返回一個新的承諾(一個解決失敗爲從bb中的'then'開始嗎?如果只是「連鎖失敗」不起作用,那麼......它根本就不是連鎖店。 – user2864740 2015-02-17 22:19:18

+0

你會想看看[打破諾言鏈,並調用一個函數的基礎上它的鏈斷裂](http://stackoverflow.com/q/20714460/1048572)和[處理多個捕獲在承諾鏈](http://stackoverflow.com/q/26076511/1048572) – Bergi 2015-02-17 23:55:30

回答

7
getFromDb().then (tradeData) -> 
    if tradeData 
    getLatestPrice tradeData -> 
     .then (latestPrice) -> 
     ... 
     .then -> 
     ... 
     .then -> 
     ... 
     .catch (err) -> 
     next err 
    else 
    getSomethingElse -> 
     send("no data") 

在3.0中,你將能夠做到這一點:

p = getFromDb().then (tradeData) -> 
    if not tradeData 
    send("no data"); 
    p.break() 
    else 
    getLatestPrice tradeData 
.then (latestPrice) -> 
    ... 
.then -> 
    ... 
.then -> 
    ... 
.catch (err) -> 
    next err 
+1

如果我想實現額外的分支邏輯呢?例如,如果有'tradeData'做某些步驟,如果沒有,做其他步驟? – Shamoon 2015-02-17 23:10:02

+1

@Shamoon使用'else' – Esailija 2015-02-17 23:11:37

+0

@Shamoon:當然,你也可以拋出一個「無數據」異常並[對控制流使用拒絕](http://stackoverflow.com/a/24663315/1048572 )。這將特別是「不要繼續鏈」,因爲你要求 – Bergi 2015-02-17 23:37:21

7

雖然接受的答案,但我想告訴所有的Google員工說,「休息()」功能被改變以 「取消()」

使用這樣的:

p = getFromDb().then (tradeData) -> 
    if not tradeData 
    send("no data"); 
    p.cancel(); // Look Here!!!!!!!!!!!!!!!! 
    else 
    getLatestPrice tradeData 
.then (latestPrice) -> 
    ... 
.then -> 
    ... 
.then -> 
    ... 
.catch (err) -> 
    next err 

在此之前,確保添加在C以下行onfig:

Promise.config({ 
    cancellation: true 
}); 
+0

對我有用 – anhnt 2017-03-15 16:32:51

0

我只是想知道爲什麼不考慮事實,你可以throw任何你喜歡的,不只是東西是instanceof Error的好處。這樣做被認爲是不好的做法?在我看來,這取決於你想要完成什麼。承諾鏈可以因各種原因而中斷,但總的來說,這兩個鏈會分成兩組。需要Classic error occurearly break in chain。從邏輯上講,第二個不能被認爲是應該是instance of Error

const handleError = (err) => { 
    ... 
} 

const skip = (reason, ..., ...) => { 
    /** 
    * construct whatever you like 
    * just for example here return reason 
    */ 
    return reason 
} 

Promise.resolve() 
.then(() => { 
    if (iShouldEndChainEarlier) { 
    throw skip('I would like to end chain earlier') 
    } 

    return asyncOperation1() 
}) 
.then(results => { 
    ... 
    return asyncOperation2(results) 
}) 
.then(... => { 
    ... 
}) 
.catch(interrupt => { 
    if (interrupt instanceof Error) { 
    return handleError(interrupt) 
    } 

    /** 
    * Handle breaking promise chain earlier 
    * having interrupt reason in scope 
    */ 
}) 

如果從邏輯上講,在鏈初歇可以被視爲錯誤(這完全可以是這種情況),您可以創建自定義錯誤和兩個catch塊之間進行區分。所以只是說在處理承諾鏈中可能發生的任何中斷時,可以考慮另一種方法。

我們可以爭辯說這是否可以被認爲是針對節點中的first error pattern的東西。如果出現錯誤,最佳做法是調用回調如callback(err),其中err確實應該是instanceof Error,否則callback(null, data)。但在另一方面,記住.catch(fn)只是糖then(undefined, onRejected)對我來說,它似乎已經足夠處理onRejected參數根據你所處的情況。