我正在编写Node.JS lambda函数,我需要调用一些带有回调的API函数并传递其他参数。
代码如下:
var s3 = ...;
for (var i = 0; i < data.foo.length; i++) {
var v1 = data.foo[i].name;
console.log("Loop: " + v1);
var params = { ... };
foo.method1(params, function(err, data1) {
console.log("Method1: " + v1);
s3.putObject(....);
});
}
这是两个问题。
我不明白为什么,但在传递给foo.method1...
的回调中,我总是具有v1
的相同值(我猜它是数组中的最后一个)。 / p>
亚马逊游戏机的代码检查器告诉我在循环中创建函数是一种不好的做法:
不要在循环中创建函数。
我猜,p.1与p.2 :-)有某种关系这就是为什么我试图创建一个命名函数并将其引用传递给foo.method1
。但它不起作用,因为我无法传递其他参数v1
和s3
。我只能将其调用包裹起来:
foo.method1(params, function(err, data1) {
myCallback(err, data1, v1, s3);
});
提示:foo.method1
显然是异步的。
我怀疑如何解决这个问题?
答案 0 :(得分:2)
这是一个常见问题,称为&#34;关闭循环变量&#34;。问题是,当您等待回调执行时v1
将继续更改,并且您看到的v1
将是它所采用的最后一个值。
解决此问题的一种方法:在回调中绑定v1
变量:
var s3 = ...;
for (var i = 0; i < data.foo.length; i++) {
var v1 = data.foo[i].name;
console.log("Loop: " + v1);
var params = { ... }; // v-- extra parameter
foo.method1(params, function(v1inner, err, data1) {
console.log("Method1: " + v1);
s3.putObject(....);
}.bind(null, v1)); // <-- bind
}
更好的方法:使用.forEach
,以便为每次迭代创建一个新的v1
变量:
var s3 = ...;
data.foo.forEach(function (datai) {
var v1 = datai.name;
console.log("Loop: " + v1);
var params = { ... };
foo.method1(params, function(err, data1) {
console.log("Method1: " + v1);
s3.putObject(....);
});
});
编辑如果您正在寻找一种更加无压力的方式来处理异步代码,我建议您查看Promises,截至目前,这是异步的未来JavaScript中的代码。这将允许您轻松管理异步操作,例如,在所有这些操作完成后执行一些代码(如果您想这样做)。
答案 1 :(得分:1)
- 我不明白为什么,但内部回调传递给foo.method1 ...我总是有相同的v1值(我猜它是最后一个)。
醇>
你得到了相同的v1
项,因为你正在迭代异步函数,所以它的内容是什么,它是迭代你的for
,然后将x
闭包({{1} })与最后一个i值`
那么你怎么能解决这个问题呢?您可以将data.foo.length
包装在IIFE中,这样就不会共享上下文。
i
此代码将使用正确的(function(i) {
var v1 = data.foo[i].name;
console.log("Loop: " + v1);
var params = { ... };
foo.method1(params, function(err, data1) {
console.log("Method1: " + v1);
s3.putObject(....);
});
})(i);
值创建一个特殊范围。
第二种方法是使用i
而不是let i
这也将使用与上述代码相同的技巧。有关let
- 亚马逊游戏机的代码检查器告诉我在循环中创建函数是不好的做法
醇>