将数据注入异步回调(使用node.js)

时间:2012-08-17 09:27:44

标签: javascript node.js asynchronous callback coffeescript

我试图围绕如何使异步编程工作。

在我目前的用例中,我的函数可能每秒被多次调用,并且它们的回调依赖于可能在它们之间发生变化的多个变量。

一个简单的例子:(为了简洁起见使用coffeescript)

doSomething = (requestor, thing, action, callback) ->
  thing.takeAction action, (result) ->
    # actually a lot of times this nests down even further
    requestor.report result
    callback result

如果doSomething在thing.takeAction返回其结果之前多次使用不同的数据被调用,我认为我不能依赖请求者和回调仍然是我需要它们的相同事物。 正确的吗?

为了避免这种情况,我需要以某种方式将请求者和回调注入takeAction的回调。 这有可能吗?

我想到了做

这样的事情
doSomething = (requestor, thing, action, callback) ->
  thing.takeAction action, (result, _requestor = requestor, _callback = callback) ->
    _requestor.report result
    _callback result

但那当然只是一个CoffeeScript黑客,根本不起作用。


顺便说一句,我试图使用caolan / async模块来帮助我解决这个问题,但事实仍然是我在回调中经常需要比async允许的更多变量。 像:

doSomething = function(requestor, thing, action, callback) {
  // this might not need a waterfall, but imagine it would have nested further

  async.waterfall(
  [
    function(next) {
      thing.takeAction(action, function(result) {
        // How can I know that action is still the same?
        next(null, result);
      });
    }, 
    function(result, next) {
      requestor.report(result); // requestor still the same?
      next(null, result);
    }
  ],

  function(err, result) {
    callback(result); // callback still the same?
  });
}

它仍然让我遇到同样的问题。那我该怎么做呢?

感谢您的时间。

1 个答案:

答案 0 :(得分:2)

您需要将action对象内容与action值本身分开。也就是说,内存中有一些对象,在此特定上下文中由action名称引用。

例如,

function test(action) {
    alert("Test1: " + action.value);
    setTimeout(function () { alert("Test2: " + action.value); }, 1000);
}

var action = { value: 1; };
test(action);
action = { value: 2 };
alert("Action value outside: " + action.value);

将提示"测试1:1","外面的动作值:2"和"测试1:1"。但是,将action = { value: 2 };替换为action.value = 2后,最后一次提醒将更改为" Test1:2"。

因此,如果您的问题是操作对象的某些字段在外部更改,只需在doSomething的第一行中克隆它。如果您的问题是在外面更改了对象的引用,您不必担心,它不会以任何方式影响您的doSomething

此外,随后对doSomething的调用不会覆盖"回调中action参数的值,因为它在特定调用时关闭:en.wikipedia.org/wiki/Closure_(computer_science)

例如,

function test(action) {
    alert("Test1: " + action.value);
    setTimeout(function () { alert("Test2: " + action.value); }, 1000);
}

var action = { value: 1; };
test(action);
action = { value: 2 };
test(action);

将提示"测试1:1","测试1:2","测试2:1"和"测试2:2" (不是" Test1:1"," Test1:2"," Test2:2"" Test2:2"因为你似乎害怕)。