我试图围绕如何使异步编程工作。
在我目前的用例中,我的函数可能每秒被多次调用,并且它们的回调依赖于可能在它们之间发生变化的多个变量。
一个简单的例子:(为了简洁起见使用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?
});
}
它仍然让我遇到同样的问题。那我该怎么做呢?
感谢您的时间。
答案 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"因为你似乎害怕)。