我正在“玩”javascript上的异步调用,我试图让下一个示例工作,但不能:
// calls function f on next event loop
function callAsync(f, ...args) {
setTimeout(() => f(...args), 0);
}
var f = (a, b, cb) => cb(null, a + b);
f2 = () => {
a = 2;
b = 3;
setTimeout(() =>
f(a, b, (err, res) => {
if (!err) console.log(res);
}), 0);
callAsync(f, a, b, (err, res) => {
if (!err) console.log(res);
});
a = 10;
b = -10;
}
f2();
所以,通过运行它,你得到的结果是:
0
5
为什么callAsync不起作用 - 这是我的问题!
答案 0 :(得分:3)
不同之处在于评估a
和b
的时间。将闭包传递给setTimeout
时,在执行使用它们的闭包时 - 在重新分配它们之后,变量将被读取。当您将a
和b
传递给callAsync
时,会立即将其作为通话的一部分进行评估。 callAsync
内的关闭只会看到值args = [2, 3, (…)=>{…}]
。
答案 1 :(得分:1)
这可能会说清楚。这里,大概是采取的步骤:
define callAsync
define f
define f2
f2()
a = 2
b = 3
+------- setTimeout(() => f(a, b, callbackFn1), 0)
| callAsync(f, 2, 3, callbackFn)
| +------- setTimeout(() => f(2, 3, callbackFn2), 0)
| | a = 10
| | b = -10
| | end f2
+----> f(10, -10, calllbackFn1)
| callbackFn1(null, 10 + -10)
| if (!err) console.log(res)
| console.log(0) //~> 0
| end f
+--> f(2, 3, callbackFn2)
callbackFn2(null, 2 + 3)
if (!err) console.log(res)
console.log(5) //~> 5
end f
答案 2 :(得分:1)
您的callAsync完全异步,但在您致电a
时会复制b
和callAsync
的值。它相当于:
setTimeout((a,b) =>
f(a, b, (err, res) => {
if (!err) console.log(res);
}), 0, a, b);
要实现您想要的目标,您可以使用一个对象,因为它们是引用类型,当您将它们作为参数传递时,它们不会被复制:
// calls function f on next event loop
function callAsync(f, ...args) {
setTimeout(() => f(...args), 0);
}
var f = (data, cb) => cb(null, data.a + data.b);
var data = {
a: 2,
b: 3,
};
callAsync(f, data, (err, res) => {
if (!err) console.log(res);
});
data.a = 10;
data.b = -10;