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 回答