2016-12-11 4 views
8

私は、約束が拒否された場合にチェーンが壊れるように約束を連鎖しようとしています。私はprevious SO questionのリードに続き、本来の約束にそれを適用しようとしましたが、私は物事の仕方を誤解していると思います。きれいな方法でjavascript promise chainを破る

Promise.resolve() 
    .then(function() { 
     return step(1) 
      .then(null, function() { 
       stepError(1); 
      }); 
    }) 
    .then(function() { 
     return step(2) 
      .then(null, function() { 
       stepError(2); 
      }); 
    }) 
    .then(function() { 
     return step(3) 
      .then(null, function() { 
       stepError(3); 
      }); 
    }); 

function step(n) { 
    console.log('Step '+n); 
    return (n === 2) ? Promise.reject(n) : Promise.resolve(n); 
} 

function stepError(n) { 
    console.log('Error '+n); 
    return Promise.reject(n); 
} 

上記のコードの出力は次のとおりです:私の理解で

Step 1 
Step 2 
Error 2 
Step 3 
[UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): 2] 

、ステップ2は、チェーンを破る必要がありますし、ステップ3はいけない。ここ

は、私は、コードを書き換えてきた方法です実行される。ステップ(2)が拒否された約束を返すと、stepError(2)が期待通りに実行されます。しかしPromise.reject(2)を返すので、次の関数は実行されてはならず、最後にcatchがないので、ステップ2の拒否された約束は、期待通りに、それはハンドラが見つからなかったからです。

私はここで何が欠けていますか?ここで

はと遊ぶのがJSFiddleです:私の理解ではhttps://jsfiddle.net/6p4t9xyk/

答えて

10

、ステップ2は、チェーンを破る必要があります...

それだろうが、あなたは誤っていることを変換しました解決への拒否。

約束に関する重要な事はthenへのすべての呼び出しが解決される新しい約束は/ thenコールバック(s)は何に基づいて拒絶され、拒絶反応を処理するコールバックがない限り、解決にその拒否を変換作成することです意図的にそうではありません。だからここ

:そう、あなたがエラーを補うため、エラーハンドラを持つことができるということだ

return step(2) 
    .then(null, function() { // This handler converts the 
     stepError(2);   // rejection into a resolution 
    });      // with the value `undefined` 

stepErrorが拒絶反応を返すので、あなただけのreturnを追加することにより、拒絶反応を続けることができる:

return step(2) 
    .then(null, function() { 
     return stepError(2); // Added `return` 
    }); 

...または交互に、完全にそのハンドラを削除:

return step(2); 

を...かあなたはthrowをコールバックに入れることができます。これは自動的に拒否に変わります。

未処理の拒否警告は、拒否をstepErrorから消費しないことが原因で発生します。@TJCrowderが言ったように

Promise.resolve() 
 
    .then(function() { 
 
     return step(1) 
 
      .then(null, function() { 
 
       return stepError(1); // Added `return` 
 
      }); 
 
    }) 
 
    .then(function() { 
 
     return step(2) 
 
      .then(null, function() { 
 
       return stepError(2); // Added `return` 
 
      }); 
 
    }) 
 
    .then(function() { 
 
     return step(3) 
 
      .then(null, function() { 
 
       return stepError(3); // Added `return` 
 
      }); 
 
    }); 
 

 
function step(n) { 
 
    console.log('Step '+n); 
 
    return (n === 2) ? Promise.reject(n) : Promise.resolve(n); 
 
} 
 

 
function stepError(n) { 
 
    console.log('Error '+n); 
 
    return Promise.reject(n); 
 
}

0

は、あなたがreturnにエラーハンドラの結果を忘れてしまった(またはからthrowへ:


はここstepErrorの結果を返す例ですそれ)。それを修正するために、私はどちらか

function withStepError(n, promise) { 
    return promise.catch(function(err) { 
     console.log('Error '+err+' from '+n); 
     throw new Error("failed at "+n); 
    }); 
} 
Promise.resolve() 
.then(function() { 
    return withStepError(1, step(1)); 
}) 
.then(function() { 
    return withStepError(2, step(2)); 
}) 
.then(function() { 
    return withStepError(3, step(3)); 
}); 

または

function getStepError(n) { 
    return function(err) { 
     console.log('Error '+err+' from '+n); 
     throw new Error("failed at "+n); 
    }; 
} 

Promise.resolve() 
.then(function() { 
    return step(1).catch(getStepError(1)); 
}) 
.then(function() { 
    return step(2).catch(getStepError(2)); 
}) 
.then(function() { 
    return step(3).catch(getStepError(3)); 
}); 
を行うことをお勧めしたいです
関連する問題