使用封闭作用域中的变量的函数节点数组



>我正在尝试使用async.parallel()对 ip 列表进行dns.reverse()

代码如下:

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(数据数组中的最后一个(进行调用。可能是我做错了什么。有人可以解释我的错误是什么吗?

第一个回调在整个 for 循环完成后执行,因为它是异步的。 ip 的值将是循环最后一次迭代中的值。 你可以放一些控制台.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);  
})

多亏@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);
});

对于任何有兴趣了解以下内容的人可能会有所帮助:JavaScript 闭包是如何工作的?

最新更新