2015-11-06 71 views
0

我在想以下是否爲正常行爲?何時 - 出現中間錯誤的意外承諾鏈

代碼

var when = require('when'); // I'm using [email protected] node_modules/when 

console.log("INIT"); 

when.promise(function(resolve, reject) { 
    return when.reject("false") 
    .then(function(ok) { 
     console.log("Step 1 - in then, ok = %s", ok); 
     return 'ok1'; 
    }, function(err) { 
     console.log("Step 1.1 - in catch, err = %s", err); 
     return reject(err); 
    }).then(function(ok) { 
     console.log("Step 2 - in then, ok2 = %s", ok); 
     return resolve("done"); 
    }).catch(function(err) { 
     console.log("Step 3 - in catch, err = %s", err); 
     return reject(err); 
    }); 
}).then(function(mainok) { 
    console.log("Step 9 - in main then, mainok = %s", mainok); 
}).catch(function(err) { 
    console.log("Step 9 - in main catch, err = %s", err); 
}); 

這是我收到的輸出運行它

INIT 
Step 1.1 - in catch, err = false 
Step 2 - in then, ok2 = undefined 
Step 9 - in main catch, err = false 

當讀API我期待這一步驟1.1將被調用,那麼第9步而不是第2步。

這是一個錯誤還是我誤讀了API?

感謝您的提示!

+1

請注意[反模式](https://github.com/petkaantonov/bluebird/wiki/Promise-anti-patterns)(創建不必要的承諾時,您可以使用/返回已有的)。 – jfriend00

+0

避免['Promise'構造函數反模式](http://stackoverflow.com/q/23803743/1048572)! – Bergi

回答

0

是的,這是預期的行爲。下面是我看到的步驟:

  1. 您創建等待resolve()reject()被稱爲它的外部承諾。
  2. 然後,您創建一個開始拒絕的內部承諾。
  3. 然後,它會轉到第一個處理程序的第二個處理程序(例如拒絕處理程序),您會看到「步驟1.1」輸出。
  4. 1.1處理程序然後拒絕外部承諾,但處理繼續在內部的承諾。
  5. 因爲您有一個.then()拒絕內部承諾的處理程序,並且您沒有丟棄或返回該處理程序拒絕的承諾,所以內部承諾的狀態切換爲解決。如果你「處理」了被拒絕的承諾,並且不拋棄或返回被拒絕的承諾,那麼狀態切換到履行。
  6. 因此,被調用的下一個.then()處理程序是「步驟2」,因爲承諾現在已滿足,而不是被拒絕。
  7. 解析處理程序然後調用resolve("done"),但外部承諾已被拒絕嘗試resolve()它現在什麼都不做。它的狀態已經設定,不能改變。
  8. 由於內部承諾現在已滿足,它跳過了「步驟3」.catch()處理程序。
  9. 外面的承諾早些時候被拒絕了,所以它跳過了「步驟9」.then()履行的處理程序,並且最後的.catch()處理程序「第9步 - 在主要的catch」中。

請記住,所有承諾都是異步解決或拒絕的。對外承諾調用reject()不會立即運行外承諾的.catch()處理程序。它安排它在未來運行。

+0

非常有用的感謝。那麼以我的方式使用內部承諾是否合法?或者我寧願使用Promise組合器,如.all或.join(或類似的)? – Boris

+0

@Boris:你絕對應該使用combinators,幾乎從不使用'when.promise'構造函數 – Bergi

+0

@Bergi感謝您的幫助 – Boris