Javascript 在执行下一步之前等待函数完成-node js

Javascript 在执行下一步之前等待函数完成-node js,javascript,node.js,async-await,Javascript,Node.js,Async Await,我是NodeJS新手,目前正在学习promises和Wait/async。我尝试了下面的代码,但不知道如何让代码等待函数hostping完成。我也尝试过承诺,但不能让它等待 var ping = require('ping'); var hoststatus var hosts = ['google.com']; async function test() { var connected = await hostping(hosts); console.log('connected--

我是NodeJS新手,目前正在学习promises和Wait/async。我尝试了下面的代码,但不知道如何让代码等待函数hostping完成。我也尝试过承诺,但不能让它等待

var ping = require('ping');
var hoststatus
var hosts = ['google.com'];

async function test()
{
  var connected = await hostping(hosts);
  console.log('connected--------------', connected)
  connected.then(function(hoststatus) {
    console.log('hoststatus--------------', hoststatus)
    if (hoststatus == 1) {
      console.log('faaaaaaaail-------------')
    } else {
      console.log('passssssssssssssssss-----------')
    }
  });
}

async function hostping(hosts) {
  console.log('hosts-----------', hosts)
  await hosts.forEach(async function(host) {
    await ping.sys.probe(host, async function(isAlive) {
      var msg = isAlive ? 'host ' + host + ' is alive' : 'host ' + host + ' is dead';
      console.log(msg);
      if (isAlive == 'false') {
        hoststatus = 1
      }
    });
  });

  return hoststatus;
}

test()

您正在forEach内部使用wait
forEach
,因为forEach不支持承诺,所以它不应该工作。考虑将其更改为<代码> > 或<代码>承诺。所有< /代码> ./P> 此外,探测函数是一种回调类型,不会返回承诺。你需要用承诺来包装它,等待它

function probe(host) {
  return new Promise((resolve, reject) => {
    ping.sys.probe(host, function (isAlive) {
      const msg = isAlive ? `host ${host} is alive` : `host ${host} is dead`;
      console.log(msg);
      resolve(isAlive);
    });
  });
}

async function hostping(hosts) {
  console.log("hosts-----------", hosts);
  for(const host of hosts) {
    // eslint-disable-next-line no-loop-func
    // eslint-disable-next-line no-await-in-loop
    const isAlive = await probe(host);
    if (isAlive === "false") {
      hoststatus = 1;
    }
  }
  return hoststatus;
}


这应该可以满足您的要求,我们使用。。按顺序迭代主机的循环

ping库还有一个promise包装器,允许您跳过使用回调

您也可以使用Promise.all同时执行所有ping和probe,但我不相信这是您希望做的

我已经包括了一个hostpingVer2,它使用Promise.all,如果您想同时执行所有ping

const ping = require('ping');
const hosts = ['google.com', 'amazon.com', 'itdoesntexist'];

async function test() {
    console.log('hosts: ', hosts)
    const results = await hostping(hosts);
    console.log('ping results: ', results);
}

async function hostping(hosts) {
    const results = [];
    for(let host of hosts) {
        let probeResult = await ping.promise.probe(host);
        results.push( { host, hoststatus: probeResult.alive ? 0: 1, alive: probeResult.alive } );
    }
    return results;
}

async function hostpingVer2(hosts) {
    const probeResults = await Promise.all(hosts.map(host => ping.promise.probe(host)));
    return probeResults.map(probeResult => { 
        return { host: probeResult.host, hoststatus: probeResult.alive ? 0: 1, alive: probeResult.alive } 
    });
}

test();

要做您想要做的事情,您应该使用ping的promise包装器,也可以使用for..of,因为forEach不能与async一起工作

  • hostping函数必须返回测试将等待的承诺 因为
  • 用于在主机上进行内部循环
  • 使用ping的promise包装器并等待探测结果
  • 检查所有主机后,解决总体状态
下面是对代码的修改,以使流程按预期工作:

const ping = require('ping');
const hosts = ['google.com', 'yahoo.com'];

async function test()
{
  const status = await hostping(hosts);

    if (status) {
        console.log('All hosts are alive');
    } else {
        console.log('Some/all hosts are dead');
    }

}

function hostping(hosts) {
    let status = true;
    return new Promise(async function(resolve, reject) {
      for (const host of hosts) {
        const res = await ping.promise.probe(host);
        var msg = `host ${host} is ${res.alive ? 'alive' : 'dead'}`;
        console.log(msg);
        if (!res.alive) { status = false; }
      }
        console.log('all host checks are done, resolving status');  
        resolve(status);
    });
}

test()
如果您有兴趣了解更多有关异步的信息,请阅读以下文章:


当您使用
等待时
您不需要使用
.then()
。请查看承诺。all@EugenSunic-谢谢你的评论。我试过了,但还是遇到了同样的问题<代码>变量ping=需要('ping');var hoststatus var hosts=['google.com'];const promise1=new Promise(函数(resolve,reject){hosts.forEach(函数(host){ping.sys.probe(host,函数(isAlive){var msg=isAlive?'host'+host+'is alive':'host'+host+'is dead';console.log(msg);});});resolve('host check is completed');然后(函数(值){console.log(值);})因为
数组#forEach
返回
未定义的
您不能等待它-使用香草for循环-而且,我怀疑
ping.sys.probe
返回承诺,因为它需要回调-所以您也不能等待它。。。既然回调函数(
function(isAlive)
)从不使用
await
,为什么要将其设置为
async
——似乎您已经阅读了async/await的相关内容,并在没有用的地方使用了它——还有最后一件事。。。为什么
hoststatus
global?你可以在forEach中使用wait和
async
回调-它的工作原理与你想象的不一样。你能给我一个例子或文档说明async/promises等在forEach中工作吗?定义“工作”。。。当然它是“有效的”,只是不像你想象的那样“有效”。。。说
forEach不支持承诺
是错误的看法,因为在forEach循环中可以很容易地使用承诺-当然,在forEach循环中使用承诺的大多数实例在map
ping.sys.probe(host,async function(isAlive))中工作得更好{
哦,天哪……为什么会有异步呢?
var-ping=require('ping');var-hoststatus-var-hosts=['google.com'];异步函数test(){var-connected=wait-hostping(hosts);console.log('connected-------',connected)}异步函数hostping(hosts){console.log('hosts-------',hosts)for(主机的const host){wait ping.sys.probe(主机,异步函数(isAlive){var msg=isAlive?'host'+host+'is alive':'host'+host+'is dead';console.log(msg);if(isAlive='false'){hoststatus=1}};}返回主机状态;}test
真的非常欢迎您!谢谢您的提问!您好,谢谢您的帮助。但是,即使所有服务器都处于活动状态,此操作也会将状态返回为false
主机google.com处于活动状态主机192.168.xx.xxx处于活动状态所有主机检查均已完成,正在解决状态----------false部分/所有主机均已死亡
更改if(res.alive)如果(!res.alive){status=false;}像charmasync承诺构造函数执行器一样工作,则通常意味着有更好的方法来编写代码