中斷或取消Promise鏈的可行方案

2022-07-07 07:36:09 字數 3469 閱讀 2936

es6標準引入的非同步程式設計解決方案promise,能夠將層層巢狀的**轉化成扁平的promise鏈式呼叫,優雅地解決了「**地獄」的問題。

當promise鏈中丟擲乙個錯誤時,錯誤資訊沿著鏈路向後傳遞,直至**獲。利用這個特性能跳過鏈中函式的呼叫,直至鏈路終點,變相地結束promise鏈。

1

promise.resolve()

2 .then(() =>)

6 .then(() => )

9 .catch(err =>);

12//

=> [onfulfilled_1]

13//

=> [catch] throw on onfulfilled_1

然而,若鏈路中也對錯誤進行了捕獲,則後續的函式可能會繼續執行。

1

promise.resolve()

2 .then(() =>)

6 .then(() =>, err => )

11 .then(() => )

14 .catch(err =>);

17//

=> [onfulfilled_1]

18//

=> [onrejected_2] throw on onfulfilled_1

19//

=> [onfulfilled_3]

解決方案

promise的then方法接收兩個引數:

promise.prototype.then(onfulfilled, onrejected)

若onfulfilled或onrejected是乙個函式,當函式返回乙個新promise物件時,原promise物件的狀態將跟新物件保持一致,詳見promises/a+標準。

因此,當新物件保持「pending」狀態時,原promise鏈將會中止執行。

1

promise.resolve()

2 .then(() =>); //

返回「pending」狀態的promise物件5})

6 .then(() => )

9 .catch(err =>);

12//

=> [onfulfilled_1]

主要問題是:鏈式呼叫時,想在下層返回resolve的情況下,需要在中途得到某種resolve結果就終止呼叫鏈。(ps:下層可能是呼叫其他人編寫模組,比如引數不對,它仍會返回resolve,出現錯誤才會reject,本身下層promise 返回reject是可以打斷呼叫鏈的)

下面有個鏈式呼叫promise的測試函式

1 const promisefun = function

(param1));5}

6 const promisetest = function

(param1, param2)`);

10return promisefun(2);

11 }).then((number)=>`);

13return promisefun(3);

14 }).then((number)=>`);

16return promisefun(4);

17 }).then((number)=>`);

19 }).catch((err)=>`);

21});

22}); 23}

24 promisetest('1','2').then((number)=>`);

26 }).catch((err)=>`);

28 });

現在遇到的乙個問題是,比如我們在fun2時,我們呼叫reject 想終止該鏈式呼叫,但實際的結果是仍然會跑到

1 console.info(`fun3 result:$`)及console.info(`fun4 result:$`)。

ps: 這種想法本身就很奇怪,因為我們呼叫reject 只是影響promisetest 下建立那個promise的狀態。也就是呼叫reject後promisetest 這個函式會觸發onrejected狀態。而鏈式promise呼叫狀態是由下層promise物件的狀態決定。

1 promisefun(1).then((number)=>`);

3return promisefun(2);

4 }).then((number)=>`);

6if(number === 2)

9else

12 }).then((number)=>`);

14return promisefun(4);

15 }).then((number)=>`);

17 }).catch((err)=>`);

19 });

2.2 原因

promise的then方法接收兩個引數:

promise.prototype.then(onfulfilled, onrejected)

若onfulfilled或onrejected是乙個函式,當函式返回乙個新promise物件時,原promise物件的狀態將跟新物件保持一致。

來自:解釋下原因:

為什麼我們鏈式呼叫中reject沒有作用?

因為reject僅僅改變的是外層包的promisetest 返回promise狀態。而鏈式呼叫的狀態是由promisefun 返回的狀態決定, 而在第二個鏈式呼叫then時我們呼叫reject改變了promisetest 那種promise的狀態進而使promisetest觸發onrejected狀態列印 promisetest failed:$,而鏈式第二個鏈式呼叫中本身沒做修改鏈式呼叫的狀態,所以第三個鏈式繼承了第乙個鏈式呼叫返回的promise的resolve狀態,導致鏈式呼叫繼續向下執行。

2.3 解決方案

而針對上面的問題,我們想要在resolve的情況下,中斷或終止鏈式呼叫。

還是基於promise的特點:原promise物件的狀態將跟新物件保持一致。

我們僅需要在鏈式呼叫中,返回乙個pending 狀態或reject狀態的promise物件即可。後面then 所有resolve(onfulfilled)的處理函式就都不會跑到了。即:

1

return (new promise((resolve, reject)=>{}));//

返回pending狀態

2return (new promise((resolve, reject)=>));//

返回reject狀態 會被最後catch捕獲。

在測試**中就想這樣

then((number)=>`);

if(number === 2)));

reject(number)

}else

Promise鏈式呼叫 終止或取消

promise 分兩種方法,then成功,catch失敗 let promise new promise function resolve,reject promise.then function val then function val catch function val 第三種方法有點粗暴,...

promise的異常鏈

var q require q 需要先用npm安裝node.js q模組 var retpromise function issuc else return deferred.promise retpromise false then function data then function data...

Channel(一) 可中斷的能力

channel可相應中斷進入關閉狀態。關鍵在於使用abstractinterruptiblechannel的begin 和end completed 方法。1 在begin 方法中 建立了interruptible介面的物件 interruptor中斷器,並使用blockon interruptor...