【问题标题】:Reduced nesting with async.waterfall but added clutter使用 async.waterfall 减少嵌套,但增加了混乱
【发布时间】:2012-08-27 17:25:16
【问题描述】:

我试图通过使用async.waterfall 来减少异步调用(node + socket.io)的嵌套,但我最终不得不将参数附加到瀑布下方,因为以后需要它们。这段代码可能解释得更好:

// 原版:

 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 之前声明变量并根据需要存储参数以供以后在链中使用,但这对可读性没有帮助。

有没有办法让它更优雅?

【问题讨论】:

  • 老实说,它看起来很优雅。

标签: node.js node-async


【解决方案1】:

我很好奇瀑布中第一个设置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)。

【讨论】:

  • 这就像一个魅力!我根据文档中记录的要求手动调用回调:tasks - 要运行的函数数组,每个函数都传递了一个回调,它必须在完成时调用。我没有意识到这已满足我正在调用的函数。瀑布现在对我来说似乎更有用了,谢谢!
  • 是的,这是 JavaScript 中的一种模式,当回调与您正在调用的函数具有相同的参数时;我在这里更多地谈论这个:nodecasts.net/episodes/5-thinking-asynchronously
  • 其实我说得太早了。它在将回调传递给套接字 api 时滚动到下一个函数,但我自己的函数作为错误滚动到最终的可选回调。在调试器中看起来不错,所以我不确定为什么我传递的参数在 async.js 代码中计算为错误。
  • 您是否确保在没有错误时将null 作为第一个参数传递给回调?异步遵循具有参数fn(error, others...) 的回调的Node.js 模式,因此您需要调用类似callback(null, message, game) 的东西。
  • 是的,这似乎是解决办法。我也对 socket.set 的行为做出了错误的假设,这使我的 var 超出了范围。我必须在 socket.on() 的回调中声明一个本地 var 来获取对 var 的引用,以便它可以在调用 socket.set 之后的函数中使用。我可能只是做 socket.set() 内联回调以避免这种情况,并简单地做“callback(myvar)”。另外,感谢 nodecast 链接。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-20
  • 1970-01-01
  • 2012-05-30
  • 2019-03-27
  • 1970-01-01
相关资源
最近更新 更多