在循环中使用其他参数进行回调

时间:2017-10-19 13:34:31

标签: javascript node.js callback anonymous-function

我正在编写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(....);
    });
}

这是两个问题。

  1. 我不明白为什么,但在传递给foo.method1...的回调中,我总是具有v1的相同值(我猜它是数组中的最后一个)。 / p>

  2. 亚马逊游戏机的代码检查器告诉我在循环中创建函数是一种不好的做法:

  3.   

    不要在循环中创建函数。

    我猜,p.1与p.2 :-)有某种关系这就是为什么我试图创建一个命名函数并将其引用传递给foo.method1。但它不起作用,因为我无法传递其他参数v1s3。我只能将其调用包裹起来:

        foo.method1(params, function(err, data1) { 
              myCallback(err, data1, v1, s3);
        });
    
    • 什么都没有意义,因为结果是一样的。

    提示foo.method1显然是异步的。

    我怀疑如何解决这个问题?

2 个答案:

答案 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)

  
      
  1. 我不明白为什么,但内部回调传递给foo.method1 ...我总是有相同的v1值(我猜它是最后一个)。
  2.   

你得到了相同的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

的更多信息
  
      
  1. 亚马逊游戏机的代码检查器告诉我在循环中创建函数是不好的做法
  2.   

要解决此问题,我建议您查看async npm模块。你可以找到each