11

序章

この質問は、最終的に、Bluebird での開発中に発生した問題を解決することを目的としています。ただし、いくつかのことを明確にする機会も利用しているため、補足的な質問があります。また、今後のストーリーを読んでいるときに混乱や退屈を感じる可能性があることをあらかじめお詫び申し上げます。


質問

私の理解では、Bluebird は次の戦略に従って、無視された拒否をインテリジェントにキャッチしようとします。

2 番目のアプローチは、bluebird がデフォルトで採用しているもので、2 番目のターンの開始までに拒否が処理されない場合に、登録済みのハンドラーを呼び出すことです。-- Bluebird Readme # エラー処理

ここで、最初の副次的な質問があります。「第 2 ターンの開始」とはどういう意味ですか?

同じセクションの後半で、次のことが文書化されています。

もちろん、これは完璧ではありません.Promiseがしばらくぶらぶらしていた後、何らかの理由でコードが急いでエラーハンドラーをPromiseに添付する必要がある場合、迷惑なメッセージが表示されます. その場合、.done() メソッドを使用して、ハングしている例外をスローする必要があることを通知できます。-- Bluebird Readme # エラー処理

さて、私のユースケースは次のとおりで、上記の状況に遭遇したと思います。

  • を添付する promise を提供する関数を呼び出します.catch()

    lib.loadUrls()
    .catch(function(e){console.log(e);});
    
  • 内部的に、その関数は URL1 からコンテンツをロードし、コンテンツに基づいて URL2 からコンテンツを順番にロードします。

    lib.loadUrls =
      return this.loadUrl1()
      .then(this.loadUrl2.bind(this))
    
  • このチェーンの 2 番目の promise が拒否された場合、エラーは最初に catch によって処理され、次に BluebirdsPossibly unhandled errorハンドラーによっても処理されます。

この最後の動作は望ましくなく、なぜこれを行っているのかわかりません。したがって、質問 2 は次のようになります。エラー ハンドラがアタッチされて実行されているにもかかわらず、Bluebird はエラーが「未処理」である可能性を考慮しているのはなぜですか?

どうやら、拒否が.catch(). その場合、(引用されたドキュメントによると)「を使用して.done()」解決する必要があります。

今、私はいくつかのことを試しましたが、このシナリオで「.done を使用する」方法がよくわかりません。.done()( undefinedを返すのは役に立たず、私が.finally-ing できなくなります。)

したがって、これは私.done()の 3 番目と 4 番目の質問を紹介します.finally()

編集1:バグを再現するためにいくつかのJSFiddlesを作成しました:

編集 2:開発者はバグを修正しました

4

2 に答える 2

1

処理されたエラーは報告されるべきではないため、Bluebird のバグである可能性が最も高いです (loadUrls本体でプロミスを適切に処理すると仮定します)。そのため、おそらく Bluebird イシュー トラッカーに報告する必要があります。

に関してdoneは、代わりに使用するthencatch、解決された値を処理するだけの場合に最適な純粋なアクセス関数です。

done最初の選択関数として扱い、他の約束への変換が本当に必要な場合thencatchのみ使用することをお勧めします。このようなアプローチでは、バグのあるエラーの監視に頼る必要もありません (完全にオフにするのが最善です)。

あなたの場合、次のdoneように使用する必要があります。

lib.loadUrls().done(); // eventual error will be thrown

何らかの理由でエラーを具体的に処理したい場合(たとえば、実行中のサーバーでエラーをスローしたくない場合)は、次のようにします。

lib.loadUrls().done(null, function (error) {
  // handle error
});

編集:

lib.loadUrls().catch(..)withによって返された promise をまだ処理したいことに気付きましたfinally。そのような場合done、解決策ではありません。done最終呼び出しとしてのみ使用する必要がありますが、finally次のように組み合わせることができます。

lib.loadUrls().finally(function () {
  // cleanup
}).done();
于 2014-02-18T07:58:11.833 に答える