在forEach循环完成之前解决发生的承诺

时间:2016-12-13 18:11:31

标签: javascript node.js promise

所以,我正在尝试使用节点和请求运行服务器测试功能。我的目标是运行一组服务器对象,构建成功服务器ping的数组,并返回具有最佳优先级的单个数组(硬编码到服务器对象中)。到目前为止,这是我的代码:

//brings in http script availability
var request = require('request');

//set of test servers
var serverSet = [
      {
        "url": "http://doesNotExist.askdex.co",
        "priority": 1
      },
      {
        "url": "http://tricon.co",
        "priority": 7
      },
      {
        "url": "http://offline.bing.co",
        "priority": 2
      },
      {
        "url": "http://google.com",
        "priority": 4
      },
      {
        "url": "http://yahoo.com",
        "priority": 6
      }
];

//inform user of process taking place
console.log("We are about to test some server requests for you, please stand by.");


function serverTest(url, priority) {
    //creates options to allow for request timeout
    var options = {
        url: url,
        timeout: 5000
    };
    return new Promise (
        function(resolve, reject) {
            request(options, function(err, res, body) {
                //if (err) {console.log("There was an error: " + err)};
                //test if server responds with a positive status
                if (res !== undefined) {
                    if (res.statusCode >= 200 && res.statusCode <= 299) {
                        //console.log("response from online server is " + res.statusCode);
                        resolve({"url": url, "priority": priority});
                    } else
                    if (res.statusCode >= 300 && res.statusCode <= 399) {
                        //console.log("response from redirected server is " + res.statusCode);
                        reject("The server is not working");
                    } else
                    if (res.statusCode >= 400 && res.statusCode <= 499) {
                        //console.log("response from not working server is " + res.statusCode);
                        reject("The server is broken");
                    }//==> end of inner if/else statement
                } else {
                    reject("Server is unresponsive");
                }//==> end of outer if/else statement
            });//==> end of get request
        }
    );
};

//call of function to run program
//var test0 = serverTest(serverSet[0].url, serverSet[0].priority).then(function(resolve){console.log("resolution is: "+ JSON.stringify(resolve))}).catch(function(reject){console.log(reject)});
//console.log("Test0: "+ test0);
//var test1 = serverTest(serverSet[1].url, serverSet[1].priority).then(function(resolve){console.log("resolution is: "+ JSON.stringify(resolve))}).catch(function(reject){console.log(reject)});
//console.log("Test1: "+ JSON.stringify(test1));
//var test2 = serverTest(serverSet[2].url, serverSet[2].priority).then(function(resolve){console.log("resolution is: "+ JSON.stringify(resolve))}).catch(function(reject){console.log(reject)});
//console.log("Test2: "+ JSON.stringify(test2));
//var test3 = serverTest(serverSet[3].url, serverSet[3].priority).then(function(resolve){console.log("resolution is: "+ JSON.stringify(resolve))}).catch(function(reject){console.log(reject)});
//console.log("Test3: "+ test3);
//var test4 = serverTest(serverSet[4].url, serverSet[4].priority).then(function(resolve){console.log("resolution is: "+ JSON.stringify(resolve))}).catch(function(reject){console.log(reject)});
//console.log("Test4: "+ JSON.stringify(test4));

function findServer(array) {
    var build = [];
    return new Promise (
        function(resolution, rejection) {
            array.forEach(function(server){
                serverTest(server.url, server.priority)
                    .then(function(resolve){
                        if (typeof resolve === "object") {
                            console.log("findServer resolve = " + JSON.stringify(resolve));
                            build.push(resolve);
                            console.log("build = " + JSON.stringify(build));
                            return build;
                        }
                    })
                    .catch(function(error){
                        //console.log("Error: " + error);
                    });
            });
                    resolution(build);
            // if (onlineServers.length == 0) {
            //  //console.log("No online servers.");
            //  reject('Error: No servers are online.');
            // }//==> end of if statement
        }
    )
};

findServer(serverSet).then(function(result) {
    console.log("The result is " + JSON.stringify(result));
    }).catch(function(error){
        console.log("The error is " + error);
    });
// function findServer(array) {
//  return new Promise (
//      function(resolution, rejection) {
//          var build = [];
//          array.forEach(function(server){
//              serverTest(server.url, server.priority).then(function(resolve){
//                      if (typeof resolve === "object") {
//                          console.log("findServer resolve = " + JSON.stringify(resolve));
//                          build.push(resolve);
//                          console.log("build = " + JSON.stringify(build));
//                          resolution(build);
//                      }
//                  }).catch(function(error){
//                      //console.log("Error: " + error);
//                  });
//          });
//          // if (onlineServers.length == 0) {
//          //  //console.log("No online servers.");
//          //  reject('Error: No servers are online.');
//          // }//==> end of if statement
//      }
//  )
// };




 // findServer(serverSet).then(function(result){
    //      console.log(result);
    //      console.log(onlineServers);
    //      //condition check and modification if more than one server response is successful
    //      if (result.length > 1) {
    //          result.sort(function(a,b){
    //              return a.priority - b.priority;
    //          })
    //          console.log(result[0].url + " has the lowest available priority.");
    //      } else {
    //          console.log(result[0].url + " has the lowest available priority.");
    //      }//==> end of if statement
    //  }).catch(function(error){
    //      console.log(error);
    //  });

注释掉的代码包含许多尝试来测试和找出使其工作的其他方法。

1 个答案:

答案 0 :(得分:1)

您希望使用Promise.all()等待许多Promise一直解决,直到继续,但请注意这个警告(强调我的):

  

Promise.all(iterable)方法返回一个解析时间的promise   可迭代参数中的所有promise都已解决,或拒绝   由于第一个通过的承诺拒绝

因此,在您的情况下,您需要确保传递给.all()的所有承诺都将得到解决。为此,您可以使用Promise.catch()处理来自serverTest()功能的拒绝并继续优雅地继续。

  

如果onRejected抛出一个,则catch()返回的Promise被拒绝   错误或返回一个本身被拒绝的Promise; 否则,它是   解决。

&#13;
&#13;
var serverSet = [{
  "url": "http://doesNotExist.askdex.co",
  "priority": 1
}, {
  "url": "http://tricon.co",
  "priority": 7
}, {
  "url": "http://offline.bing.co",
  "priority": 2
}, {
  "url": "http://google.com",
  "priority": 4
}, {
  "url": "http://yahoo.com",
  "priority": 6
}]

function serverTest(url, priority) {
  var options = {
    url: url,
    timeout: 5000
  }
  return new Promise((resolve, reject) => {
    // Always resolve for testing purposes
    resolve({
      "url": url,
      "priority": priority
    })
  })
}

function findServer(servers) {
  var build = []
  var promises = servers.map(server => {
    return serverTest(server.url, server.priority)
      .then(resolve => {
        // Do your validation of resolve here
        build.push(resolve)
      })
      .catch(error => {
        // By using catch, you ensure this promise chain will continue to 
        // resolve as long as you don't throw an error here or return another
        // Promise that will reject
        console.log("Server " + server.url + " failed with : " + error)
      })
  })

  return Promise.all(promises).then(values => {
    // At this point you know that all your promises have resolved, and
    // the successful ones have added an element to 'build'
    return build
  });
};

findServer(serverSet).then(result => {
  console.log("result is : " + JSON.stringify(result))
})
&#13;
&#13;
&#13;

修改:使用map()代替forEach + push(),感谢评论中的建议。

编辑2:添加了完整示例的代码,但修改了serverTest以便它始终解析,以验证findServer是否正确填充了build数组。