使用封闭范围中的变量的函数的节点数组

时间:2018-06-27 21:43:47

标签: node.js node-async

我正在尝试使用dns.reverse()在ip列表上执行async.parallel()

代码如下:

var functions = [];
for (var i = 0; i < data.length; i++) {
    var ip = data[i].ip;
    var x = function(callback) {
        dns.reverse(ip, (err, hostnames) => {
            if (err) {
                log.error("Error resolving hostname for [" + ip + '] ' + err);
                return callback(null, err);
            }

            callback(null, hostnames);
        });
    };

    functions.push(x);
}

async.parallel(functions, (err, results) => {
    for(var i = 0; i < data.length; i++) {
        data[i]['hostnames'] = results[i];
    }

    handler(null, data);
});

正在发生的情况是,dns.reverse()被所有调用使用相同的ip(数据数组中的最后一个)调用。可能是我做错了。有人可以解释我的错误吗?

2 个答案:

答案 0 :(得分:0)

第一个回调是在整个for循环完成之后执行的,因为它是异步的。 ip的值将是循环的最后一次迭代中的值。 您可以放置​​一些console.log来了解实际情况。

正确的做法可能是:

async.parallel(data.map(({ ip }) => callback => {
    dns.reverse(ip, callback)
}), (err, results) => {
    for (var i = 0; i < data.length; i++) {
       data[i]['hostnames'] = results[i];
    }

    handler(null, data);  
})

基于每个ip创建一个新的函数数组。 每个函数都将其回调称为dns.reverse。

此外,最好返回一个新的数据数组,而不要在循环内更改数据:

(err, results) => {
  const result = data.map((data, index) => ({
      ...data,
      hostnames: results[index]
  })

  handler(null, result);  
})

答案 1 :(得分:0)

感谢@apokryfos,我得到了一个提示。为了使代码正常工作,我只需要在声明ip时使用let而不是var。

        var functions = [];
        for (var i = 0; i < data.length; i++) {
            let ip = data[i].ip;
            var x = function(callback) {
                dns.reverse(ip, (err, hostnames) => {
                    if (err) {
                        log.error("Error resolving hostname for [" + ip + '] ' + err);
                        return callback(null, err);
                    }

                    callback(null, hostnames);
                });
            };

            functions.push(x);
        }
        async.parallel(functions, (err, results) => {
            for(var i = 0; i < data.length; i++) {
                data[i]['hostnames'] = results[i];
            }

            handler(null, data);
        });

对于任何有兴趣了解以下内容的人可能会有所帮助:How do JavaScript closures work?