Async: エラーをスローせずにウォーターフォールチェーンを切断する

作成日 2011年02月15日  ·  8コメント  ·  ソース: caolan/async

非同期ウォーターフォールを使用しているコードをリファクタリングする必要があると言われました。 主に、連鎖関数が深すぎて、関数を再利用したかったために使用しました。チェーンのある時点で、厳密にはエラー条件ではない条件がありますが、そうではありません。ウォーターフォールチェーンの残りの部分を渡したいのですが、それは役に立たないからです。たとえば、クエリを実行しても結果がない場合、それはエラーではありません。結果がないまま完全に伝播したくないとします。 非同期なしでこれを実行している場合、「最終的な」コールバックがあり、明示的にエラーをスローせずにチェーンから抜け出すために呼び出すことができると思います。 この機能はウォーターフォールには存在しないようです。 これをきれいに行う方法はありますか? 私がそれを行うために見ることができる唯一の方法は、特別なエラーをスローし、それを最後のコールバックで処理して、エラー以外を返すことです。

最も参考になるコメント

個人的には、このような機能が必要であり、コアライブラリに追加する必要があると思います。

誰かが興味を持っている場合は、これが私のヘルパーの回避策です...

exports.breakWaterfall = function(tasks, callback){
    async.waterfall(tasks, function(){
        if(arguments[0] === 'break'){
            arguments[0] = null;
        }
        callback.apply(null, arguments);
    });
}

タスク内の最後の関数に割り込む必要がある場合は、 done('break', other, arguments);ようにコールバックを呼び出すだけです。

ヘルパーは'break'を検出し、引数を変更するだけなので、コードの残りの部分ではエラーのようには見えません。

全てのコメント8件

こんにちは、

あなたはおそらく今までにあなたの問題を解決しました、ところでこれは私のアプローチです:

var flow = [
    async.apply(...),
    // ...
];

async.waterfall(flow, function (err) {
    if (err === 'ok') return;
    // handle error
});

関数がerr = 'ok'てコールバックを呼び出すと、ウォーターフォールの最後のコールバックがそれをインターセプトします。

同様の問題があり、使用するすべてのウォーターフォールでエラーかどうかを確認するために、コールバックラッパー(回避できます)を追加しています。 複数の滝がある場合はそれほどきれいではありません。
コールバック関数自体に「final」と呼ばれる別のプロパティを含めることができますか?これを呼び出して最後に移動できます。
何かのようなもの

function search (cond, callback) {
  async.waterfall([function (cb) {
      db.get(cond, cb);
    },
    function (res, cb) {
      if (!res || !res.length)
        return cb.final();
      //do something useful
    }
  ], callback);
}

コールバックをラップする必要はありません。プログラムの残りの部分にチェーンすることができます。

@caolan @jnordbergプルリクエストについてはありますか? もしそうなら、このプルリクエストを受け入れるために私ができることはありますか?

@tax :実際、次のように 'error' = trueを渡すことで、最後の関数にスキップできることがわかりました。

async.waterfall([関数(コールバック){
コールバック(null); // <---次のfnに移動
}、
関数(コールバック){
コールバック(true); // <---最後のfnにスキップ
}、
関数(コールバック){
コールバック(null); // <---このfnは呼び出されません
}
]、 折り返し電話);

@ tot2ivnヒントをありがとう!

ただし、エラーを設定すると、結果は空になります。

var async = require('async');

async.waterfall( [
  function( callback ){
    console.log('one');
    callback( null );
  },

  function( callback ){
    console.log('two');
    callback( true, 'more info' );
  },

  function( callback ){
    console.log('three');
    callback( null );
  }
], function(err, result){
  console.log( err, result );
} );

// RESULT
// one
// two
// true undefined

プルリクエスト#85を閉じる際の@caolanのコメントに

個人的には、このような機能が必要であり、コアライブラリに追加する必要があると思います。

誰かが興味を持っている場合は、これが私のヘルパーの回避策です...

exports.breakWaterfall = function(tasks, callback){
    async.waterfall(tasks, function(){
        if(arguments[0] === 'break'){
            arguments[0] = null;
        }
        callback.apply(null, arguments);
    });
}

タスク内の最後の関数に割り込む必要がある場合は、 done('break', other, arguments);ようにコールバックを呼び出すだけです。

ヘルパーは'break'を検出し、引数を変更するだけなので、コードの残りの部分ではエラーのようには見えません。

このページは役に立ちましたか?
0 / 5 - 0 評価