6

を使用して非同期呼び出し (node + socket.io) のネストを削減しようとしてasync.waterfallいますが、後で必要になるため、ウォーターフォールにパラメーターを追加する必要がありました。このコードはよりよく説明するかもしれません:

// 元のバージョン:

 socket event: turn action
  socket.on('turn action', function(gameId, turnAction, clientFn) {
    socket.get('corp', function(err, corp) {
      gameProvider.processTurnAction(gameId, corp.id, turnAction, function(err, msg, game) {
        clientFn(msg, game);
      });
    });
  });

// async.js バージョン

  async.waterfall([
    function(callback) {
      socket.on('turn action', function(gameId, turnAction, clientFn) {        
        callback(null, gameId, turnAction, clientFn);
      });
    },
    function(gameId, turnAction, clientFn, callback) {
      socket.get('corp', function(err, corp) {
        callback(null, gameId, turnAction, clientFn, corp);
      });
    },
    function(gameId, turnAction, clientFn, corp, callback) {
      gameProvider.processTurnAction(gameId, corp.id, turnAction, function(err, msg, game) {
        clientFn(msg,game);
      });
    }
  ]);

目標は読みやすさでしたが、冗長なパラメーターの受け渡しが混乱を招くことがわかりました。async.waterfall を呼び出す前に変数を宣言し、後でチェーンで使用するために必要に応じてパラメーターを保存できることはわかっていますが、読みやすさには役立ちません。

これをよりエレガントにする方法はありますか?

4

1 に答える 1

5

turn actionハンドラーを設定するウォーターフォールの最初の関数に興味があります。イベント ハンドラーを指定するだけなので、技術的には同期的です (ハンドラー自体は非同期で呼び出されますが)。私はおそらくそれを次のようにリファクタリングします:

socket.on('turn action', function(gameId, turnAction, clientFn) {
  async.waterfall([
    function(callback) { socket.get('corp', callback); },
    function(corp, callback) {
      gameProvider.processTurnAction(gameId, corp.id, turnAction, callback);
    }
  ], function(err, msg, game) {
    // err will be set if either of the two `callback`s were called with
    // an error as the first parameter
    clientFn(msg, game);
  });
}

これには、任意のパラメーターを最終的なコールバックに渡すという追加の利点があるerrorため、必要に応じてそれらを処理できます (たとえばclientFn、エラーを指定するパラメーターを使用して呼び出します)。

于 2012-09-02T22:09:53.303 に答える