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

Injecting data into asynchronous callbacks (with node.js)

本文关键字:使用 node js 回调 数据 注入 异步      更新时间:2023-09-26

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

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

一个简化的例子:(为了简洁起见,使用咖啡脚本)

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

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

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

我有做类似事情的想法

doSomething = (requestor, thing, action, callback) ->
  thing.takeAction action, (result, _requestor = requestor, _callback = callback) ->
    _requestor.report result
    _callback result

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


顺便说一句,我试图使用 caolan/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?
  });
}

它仍然给我留下同样的问题。那么我该怎么做呢?

谢谢你的时间。

您需要

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"(而不是"测试1:1","测试1:2","测试2:2"和"测试2:2",因为您似乎害怕)。

我不确定使用 CS 是否真的对这个例子有帮助,让我用普通的 JS 来表达它:

var doSomething = function (requestor, thing, action, callback) {
    thing.takeAction(action, function (result) {
        requestor.report(result);
        callback(result);
    });
};
// Following is completely safe:
doSomething(r1, t1, a1, c1); 
doSomething(r2, t2, a2, c2); 
doSomething(r3, t3, a3, c3); 

每次调用 doSomething 时,都会创建新的函数作用域。因此,在内部,创建并传递给takeAction的函数可以访问最初调用doSomething的参数(另一个调用doSomething不会改变这一点!这就是JavaScript中范围界定

的工作方式。