从异步请求循环中获取值

Getting values from a loop of asynchronous requests

本文关键字:获取 循环 异步 请求      更新时间:2023-09-26

我正在尝试编写一个nodejs程序,查询github的repos列表(通过github API的Node包装器:https://www.npmjs.com/package/github)并检索数组中的git克隆url,然后我希望按字母顺序排序。

由于调用的异步性质,我不确定如何等到所有异步请求返回?

下面是讨论中的循环。repoArray是一个repos数组,格式为[username/rename]

var urls = [];
for (var i=0; i < repoArray.length; i++) {
    var components = repoArray[i].split('/');
    github.repos.get({
        user: components[0],
        repo: components[1]
    }, function(err, res) {
        urls.push(res.ssh_url);
    });
}
// do a case-insensitive sort
urls.sort(function(a,b) {
    return a.localeCompare(b, 'en', {'sensitivity': 'base'});
});
console.log("urls: " + urls);

基本上,由于循环中的github.repos.get()调用都是异步/基于回调的,当代码到达urls.sort()然后到达console.log()时,没有或一些github.repos.get()调用完成。

我不太熟悉承诺或延迟,但这是该走的路吗?我不确定如何重构该循环,以便在所有来自循环的请求完成后才调用urls.sort() ?

Async库就是针对这些场景的,通常人们倾向于使用它来解决这些问题。它可以帮助您并行执行异步任务,并在它们全部完成时执行回调,使用async.each.

var async = require('async');
var urls = [];
//make each HTTP request
function process(repo,callback){    
  var components = repo.split('/');
  github.repos.get({
    user: components[0],
    repo: components[1]
  }, function(err, res) {
    if(err){
      // call callback(err) if there is an error
      return callback(err);
    }
    else{
      urls.push(res.ssh_url);
      // call callback(null) if it was a success,
      return callback(null);
    }
  });
}
// this will iterate over repoArray and pass each repo to the 'process' function.  
// if any of the calls to 'process' result in an error, 
// the final callback will be immediately called with an error object
async.each(repoArray,process,function(error){
  if(error){
    console.error('uh-oh: '+error)
    return;
  }
  else{
    // do a case-insensitive sort
    urls.sort(function(a,b) {
      return a.localeCompare(b, 'en', {'sensitivity': 'base'});
    });
    console.log("urls: " + urls);
  }
});

编辑:因为你是在最后排序它们,url将是有序的。