具体来说,给定一个数据列表,我想循环遍历该列表,并在之后将其全部组合之前对该数据的每个元素进行一次获取。事实上,正如所写的那样,代码会立即遍历整个列表,立即启动所有操作。然后,即使获取操作仍然在运行,然后在完成所有运行之后调用,然后才能处理数据。
我读了一些关于将所有Promises
放入数组,然后将该数组传递给Promise.all()调用,接着是一个然后可以按预期访问所有处理过的数据的内容,但是我我不确定在这种情况下如何做到这一点,因为我在这个for循环中嵌套了Promises
。
for(var i in repoData) {
var repoName = repoData[i].name;
var repoUrl = repoData[i].url;
(function(name, url) {
Promise.all([fetch(`https://api.github.com/repos/${username}/${repoData[i].name}/commits`),
fetch(`https://api.github.com/repos/${username}/${repoData[i].name}/pulls`)])
.then(function(results) {
Promise.all([results[0].json(), results[1].json()])
.then(function(json) {
//console.log(json[0]);
var commits = json[0];
var pulls = json[1];
var repo = {};
repo.name = name;
repo.url = url;
repo.commitCount = commits.length;
repo.pullRequestCount = pulls.length;
console.log(repo);
user.repositories.push(repo);
});
});
})(repoName, repoUrl);
}
}).then(function() {
var payload = new Object();
payload.user = user;
//console.log(payload);
//console.log(repoData[0]);
res.send(payload);
});
答案 0 :(得分:4)
通常,当您需要为数组中的所有项运行异步操作时,答案是使用Promise.all(arr.map(...))
,这种情况似乎也不例外。
另请注意,您需要return
回调中的then
值才能将值传递到下一个then
(或Promise.all
聚合所有内容)。
当遇到复杂情况时,将其分解成更小的部分会有所帮助。在这种情况下,您可以隔离代码以查询单个仓库的数据到其自己的功能中。完成后,查询所有数据的代码归结为:
Promise.all(repoData.map(function (repoItem) {
return getDataForRepo(username, repoItem);
}))
请尝试以下方法:
// function to query details for a single repo
function getDataForRepo(username, repoInfo) {
return Promise
.all([
fetch(`https://api.github.com/repos/${username}/${repoInfo.name}/commits`),
fetch(`https://api.github.com/repos/${username}/${repoInfo.name}/pulls`)
])
.then(function (results) {
return Promise.all([results[0].json(), results[1].json()])
})
.then(function (json) {
var commits = json[0];
var pulls = json[1];
var repo = {
name: repoInfo.name,
url: repoInfo.url,
commitCount: commits.length,
pullRequestCount: pulls.length
};
console.log(repo);
return repo;
});
}
Promise.all(repoData.map(function (repoItem) {
return getDataForRepo(username, repoItem);
})).then(function (retrievedRepoData) {
console.log(retrievedRepoData);
var payload = new Object();
payload.user = user;
//console.log(payload);
//console.log(repoData[0]);
res.send(payload);
});