神奇的nodejs: 关于在for遍历中有异步代码块
如下代码:
(注意,ping 模块的源代码被我改过了)
执行以下的代码会出现什么问题?
numeric_host 的赋值不是按照我们想要的预定义顺序,而是会出现超前替换,或者乱序替换的问题。因为for循环里面出现了异步调用,ping.sys.probe_res的下一阶是使用的promise函数。
function get_numeric_host () {
for (var i = 0; i < domainList; i++) {
var esxihostordomain = domainList[i];
var numeric_host = '';
if (esxihostordomain != undefined && esxihostordomain != '' && esxihostordomain != 'null') {
ping.sys.probe_res(esxihostordomain, function(res) {
numeric_host = res.numeric_host;
console.log(i, numeric_host);
if (res != undefined && res != '' && res != 'null') {
console.log(res);
var msg = res.alive ? 'host: ' + esxihostordomain + ' is alive' : 'host: ' + esxihostordomain + ' is dead';
if (res.alive) {
console.log(msg);
console.log(i, numeric_host);
}
}
});
}
}
}
解决的方案如下:
添加一个异步回掉的函数,来达到阻断强制同步判断和赋值
function get(esxihostordomain, i, next){
var flag = false;
numeric_host = '';
ping.sys.probe_res(esxihostordomain, function(res) {
numeric_host = res.numeric_host;
console.log(i, numeric_host);
if (res != undefined && res != '' && res != 'null') {
console.log(res);
var msg = res.alive ? 'host: ' + esxihostordomain + ' is alive' : 'host: ' + esxihostordomain + ' is dead';
if (res.alive) {
console.log(msg);
console.log(i, numeric_host);
flag = true;
next({ 'flag': flag, 'numeric_host': numeric_host});
}
}
});
next({ 'flag': flag, 'numeric_host': numeric_host});
}
function get_numeric_host () {
for (var i = 0; i < domainList; i++) {
var esxihostordomain = domainList[i];
var numeric_host = '';
if (esxihostordomain != undefined && esxihostordomain != '' && esxihostordomain != 'null') {
get(esxihostordomain, i, function(res){
console.log(res);
});
}
}
}
或者还可以这个样子:
function get_numeric_host () {
for (var i = 0; i < domainList; i++) {
var esxihostordomain = domainList[i];
var numeric_host = '';
if (esxihostordomain != undefined && esxihostordomain != '' && esxihostordomain != 'null') {
get(esxihostordomain, i, function(res){
console.log(res);
});
}
}
function get(esxihostordomain, i, next){
var flag = false;
numeric_host = '';
ping.sys.probe_res(esxihostordomain, function(res) {
numeric_host = res.numeric_host;
console.log(i, numeric_host);
if (res != undefined && res != '' && res != 'null') {
console.log(res);
var msg = res.alive ? 'host: ' + esxihostordomain + ' is alive' : 'host: ' + esxihostordomain + ' is dead';
if (res.alive) {
console.log(msg);
console.log(i, numeric_host);
flag = true;
next({ 'flag': flag, 'numeric_host': numeric_host});
}
}
});
next({ 'flag': flag, 'numeric_host': numeric_host});
}
}