【问题标题】:Promise.all() behaving unexpectedly, where is my lack of understanding?Promise.all() 行为异常,我哪里缺乏理解?
【发布时间】:2016-09-15 19:29:36
【问题描述】:

我正在尝试编写一个使用 GitHub API 的脚本。我有一个接受用户名列表的函数。对于每个用户名,都会调用 API 以使该用户为存储库加星标。对于每个用户为 repo 加星标,我想捕获 repo 的名称和星数,最终我想对这些数据做更多的工作。

我正在尝试仅使用本机承诺来实现这一点,并避免使用 Q、Bluebird 等。这就是我所拥有的不起作用的东西。

function getNameAndStarInfo(repo){
  return new Promise(function(resolve, reject){
    //i'd like this to return an object but it has to be an iterable??
    resolve([{[repo.full_name] : repo.stargazers_count}]); 
  });
};

function getStarredRepos(usernames){
  var promises =[];
  for (var user in usernames){
    //build the header for API request

    var name = usernames[user];
    var url = 'https://api.github.com/users/' + name + '/starred';
    var header = {url: url, headers: {'User-Agent': 'username', 'Authorization': 'token blahblabhlabh'}, json: true };

    //for the current user make a request and get their starred repos
    request(header, function(err, res, usersStarredRepos){
        for (var repo in usersStarredRepos){
            promises.push(getNameAndStarInfo(usersStarredRepos[repo]));

        };
    });
   };
   Promise.all(promises)
      .then(function(promises){
        //dont need to log, would like to do stuff with this data later
        console.log(promises);
    });

};

基本上,当我在 .then() 方法中记录数组时,我希望看到所有的 {name: stargazers_count} 数据。但是每次都会输出一个空数组。有人可以向我解释一下我在这里缺少什么吗?

【问题讨论】:

标签: javascript node.js loops promise


【解决方案1】:

只有在请求已经完成时,您才promises。所以当Promise.all被执行时,数组仍然是空的,因为它们都还没有完成。

试试这个方法:

function getNameAndStarInfo(repo) {
    return new Promise(function(resolve, reject) {
        //i'd like this to return an object but it has to be an iterable??
        resolve([{
            [repo.full_name]: repo.stargazers_count
        }]);
    });
}

function getUserStars(username) {
    return new Promise(function(resolve, reject) {
        var name = username.name;
        var url = 'https://api.github.com/users/' + name + '/starred';
        var header = { url: url, headers: { 'User-Agent': 'username', 'Authorization': 'token blahblabhlabh' }, json: true };
        //for the current user make a request and get their starred repos
        request(header, function(err, res, usersStarredRepos) {
            var promises = [];
            for (var repo in usersStarredRepos) {
                promises.push(getNameAndStarInfo(usersStarredRepos[repo]));
            };
            Promise.all(promises).then(resolve).catch(reject);
        });
    });
}

function getStarredRepos(usernames) {
    var promises = [];
    for (var user in usernames) {
        promises.push(getUserStars(usernames[user]));
    }
    Promise.all(promises).then(console.log).catch(console.log);
}

但为了避免手动创建Promises 来处理请求,我建议您使用request-promise

https://www.npmjs.com/package/request-promise

【讨论】:

  • 避免Promise constructor antipattern!你应该只承诺request,并链接到它。
  • @Bergi 问题完全是关于 Promise.all 而不是 Promise 模式。他问为什么 Promise.all 没有像他预期的那样工作。我告诉他原因,然后,只是写了一个代码(按照他的模式)作为示例。关于被触发的请求数量,我没有看到这种情况发生。我发出了许多请求,每个用户一个。甚至不需要代码。他只是要求解释。
  • @DiegoZoracKy 是的,关于Promise.all 的答案是正确的,但是您编写的代码是一个不好的例子。请修复它,这种模式不应该使用。
  • @DiegoZoracKy 关于我删除的关于请求数的评论,我对函数命名感到困惑;我提出了修改建议。
猜你喜欢
  • 2011-03-04
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 2013-02-08
  • 2012-05-22
  • 2019-06-04
  • 2018-03-10
  • 1970-01-01
相关资源
最近更新 更多