异步http调用无法在循环内部运行

时间:2019-04-15 03:29:35

标签: javascript http asynchronous

为了捕获多个集群中每个节点的运行状况,我需要通过for循环内部的http调用来调用它们,但是在服务器无法使程序正常工作返回状态之前,循环结束。

module.exports = function(robot) {
  robot.respond(/nonprodoauthhealthcheck/i, function(msg){
    var healthcheck=[];
    var nodes = [{
        "cluster": ["https://testurl1.com", "https://testurl2.com"],
        "client_id": "clientid1",
        "client_secret": "password1"
      },
      {
        "cluster": ["https://testur3.com", "https://testurl4"],
        "client_id": "clientid2",
        "client_secret": "password2"
      }
    ];
    for(let i=0;i<nodes.length;i++){
      console.log("i="+i)
      client_id=nodes[i].client_id;
      client_secret= nodes[i].client_secret;
      clusteritem=nodes[i].cluster;
      for(let j=0;j<clusteritem.length;j++){
        var data="client_id="+client_id+"&client_secret="+client_secret+"&grant_type=client_credentials";
        var queryJobUrls=clusteritem[j];
        console.log("j="+j)
        getJobUrls(queryJobUrls,data)
        .then(function(response){
          //msg.reply(response)
          healthcheck.push(
            {
              "url":clusteritem[j],
              "status":response
            }
          )
        })
        .catch(function(error){
          //msg.reply(error)
          healthcheck.push(
            {
              "url":clusteritem[j],
              "status":error
            }
          )
        })
      };
      }
      //for(let k=0;k<healthcheck.length;k++){}
      msg.reply(healthcheck);
    });

  function getJobUrls(queryJobUrls,data) {
    return new Promise(function(resolve, reject){
      var options = {
        rejectUnauthorized: false
      }
       robot.http(queryJobUrls, options).header('Content-Type', 'application/x-www-form-urlencoded').post(data)(function(err, response, body) {
        console.log("inside oauth call")
        if (err != null){
          reject(err);
        }
        else {
          resolve(body);
        }
      });
    })
  }
}

我希望代码填充运行状况检查数组并看起来像这样:

healthcheck = [{"url":"http://testurl1.com",status="response from http call"},{"url":"http://testurl2.com",status="response from http call"},{"url":"http://testurl3.com",status="response from http call"},{"url":"http://testur4.com",status="response from http call"}]

1 个答案:

答案 0 :(得分:0)

在使用msg.reply参数调用healthcheck之前,您需要确保所有承诺均已解决,其结果在healthcheck中可用。在这里,我们使用Promise.all来确保这一点。

module.exports = function (robot) {
        robot.respond(/nonprodoauthhealthcheck/i, function (msg) {
            var healthcheck = [];
            var nodes = [{
                "cluster": ["https://testurl1.com", "https://testurl2.com"],
                "client_id": "clientid1",
                "client_secret": "password1"
            },
            {
                "cluster": ["https://testur3.com", "https://testurl4"],
                "client_id": "clientid2",
                "client_secret": "password2"
            }
            ];
            const promises = [];
            for (let i = 0; i < nodes.length; i++) {
                console.log("i=" + i)
                client_id = nodes[i].client_id;
                client_secret = nodes[i].client_secret;
                clusteritem = nodes[i].cluster;

                for (let j = 0; j < clusteritem.length; j++) {
                    var data = "client_id=" + client_id + "&client_secret=" + client_secret + "&grant_type=client_credentials";
                    var queryJobUrls = clusteritem[j];
                    console.log("j=" + j)
                    promises.push(getJobUrls(queryJobUrls, data, clusteritem[j]));
                }
            }
            const promise = Promise.all(promises);
            promise.then(res => {
                res.forEach(r => {
                    healthcheck.push({
                        url: r.url,
                        status: r.body
                    })
                });
                msg.reply(healthcheck);
            })
        });

        function getJobUrls(queryJobUrls, data, url) {
            return new Promise(function (resolve, reject) {
                var options = {
                    rejectUnauthorized: false
                }
                robot.http(queryJobUrls, options).header('Content-Type', 'application/x-www-form-urlencoded').post(data)(function (err, response, body) {
                    console.log("inside oauth call")
                    if (err != null) {
                        reject({ err, url });
                    }
                    else {
                        resolve({ body, url });
                    }
                });
            })
        }
    }