bluebirdの約束による非同期例外処理

Asynchronous exception handling with bluebird promises


質問 written by Bergi @2014-08-06 13:53:40Z

: 12 : 2 : 7

このシナリオを処理するための最良の方法は何ですか。 私は制御された環境にいます、そして私はクラッシュしたくありません。

var Promise = require('bluebird');

function getPromise(){
    return new Promise(function(done, reject){
        setTimeout(function(){
                throw new Error("AJAJAJA");
        }, 500);
    });
}

var p = getPromise();
    p.then(function(){
        console.log("Yay");
    }).error(function(e){
        console.log("Rejected",e);
    }).catch(Error, function(e){
        console.log("Error",e);
    }).catch(function(e){
        console.log("Unknown", e);
    });

setTimeout内からスローすると、常に次のようになります。

$ node bluebird.js

c:\blp\rplus\bbcode\scratchboard\bluebird.js:6
                throw new Error("AJAJAJA");
                      ^
Error: AJAJAJA
    at null._onTimeout (c:\blp\rplus\bbcode\scratchboard\bluebird.js:6:23)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)

スローがsetTimeoutの前に発生した場合、bluebirds catchはそれを拾います。

var Promise = require('bluebird');

function getPromise(){

    return new Promise(function(done, reject){
        throw new Error("Oh no!");
        setTimeout(function(){
            console.log("hihihihi")
        }, 500);
    });
}

var p = getPromise();
    p.then(function(){
        console.log("Yay");
    }).error(function(e){
        console.log("Rejected",e);
    }).catch(Error, function(e){
        console.log("Error",e);
    }).catch(function(e){
        console.log("Unknown", e);
    });

の結果:

$ node bluebird.js
Error [Error: Oh no!]

これは素晴らしいです - しかし、ノードやブラウザでこの種の不正な非同期コールバックをどのように処理すればよいでしょうか。

コメント 1

settimeout(または非同期メソッド)を約束にラップして、他のすべてと同じように処理されるようにします。

written by Kevin B @2014-08-05 16:28:29Z

コメント 2
回答 1 written by Bergi @2016-03-28 14:52:08Z
15

プロミスはドメインではなく、非同期コールバックからの例外をキャッチすることはありません。 あなたはそれができません。

ただし、 Promisethen / catch / Promiseコンストラクタコールバック内からスローされる例外をcatchます。 だから使う

function getPromise(){
    return new Promise(function(done, reject){
        setTimeout(done, 500);
    }).then(function() {
        console.log("hihihihi");
        throw new Error("Oh no!");
    });
}

(またはPromise.delayだけで)目的の動作を取得します。 カスタム(約束でない)非同期コールバックを決して投げ込まず、周囲の約束を拒否します。 本当に必要な場合はtry-catch使用してtry-catch

コメント 1

setTimeoutによって呼び出されたメソッドで何が起こっているのかを制御できない場合はどうすればよいですか?@Kevin Bの提案に沿って別の約束に包む?

written by j03m 14 @2014-08-05 18:28:14Z

コメント 2

それが手に負えないとき、それからあなたは誤りを捕らえることができません。あなたがコントロールを得る必要があるそのライブラリに対するバグを提出してください。

written by Bergi 14 @2014-08-05 18:36:35Z

コメント 3

うーん、モカがフードの下で何をしているかをチェックするように、何かを処理するようです:それ(「こんにちは世界で応答する必要があります」、function(done){setTimeout(function(){throw new Error( "ouch"); done( );}、500);});とても優雅に。しかし、おそらく約束はありません。

written by j03m 14 @2014-08-05 18:44:29Z

コメント 4

ブラウザではwindow.onerror使用し、ノードではドメインを使用します。

written by Bergi 14 @2014-08-05 18:47:59Z

コメント 5

ランナーの場合:process.on( 'uncaughtException'、uncaught);

written by j03m 14 @2014-08-05 19:02:43Z

回答 2 written by Solominh @2017-09-05 03:13:39Z
0

と言っています 今約束は非同期コールバックでエラーをキャッチしないことを知っています。 これが私がテストした3つの例です。

注:着信拒否の後、機能は実行され続けます。

例1:拒否してからpromiseコンストラクターのコールバックでエラーをスローする

例2:拒否してからsetTimeout非同期コールバックでエラーをスローする

例3:クラッシュしないように、拒否してからsetTimeout非同期コールバックを返す

// Caught
// only error 1 is sent
// error 2 is reached but not send reject again
new Promise((resolve, reject) => {
  reject("error 1"); // Send reject
  console.log("Continue"); // Print 
  throw new Error("error 2"); // Nothing happen
})
  .then(() => {})
  .catch(err => {
    console.log("Error", err);
  });


// Uncaught
// error due to throw new Error() in setTimeout async callback
// solution: return after reject
new Promise((resolve, reject) => {
  setTimeout(() => {
    reject("error 1"); // Send reject
    console.log("Continue"); // Print

    throw new Error("error 2"); // Did run and cause Uncaught error
  }, 0);
})
  .then(data => {})
  .catch(err => {
    console.log("Error", err);
  });


// Caught
// Only error 1 is sent
// error 2 cannot be reached but can cause potential uncaught error if err = null
new Promise((resolve, reject) => {
  setTimeout(() => {
    const err = "error 1";
    if (err) {
      reject(err); // Send reject
      console.log("Continue"); // Did print
      return;
    }
    throw new Error("error 2"); // Potential Uncaught error if err = null
  }, 0);
})
  .then(data => {})
  .catch(err => {
    console.log("Error", err);
  });