gpt4 book ai didi

Javascript:确保一个异步函数在另一个异步函数完成之前不会运行;带着 promise 工作

转载 作者:行者123 更新时间:2023-12-02 22:27:45 25 4
gpt4 key购买 nike

我正在从 github 存储库获取信息。我想要获取该存储库中的拉取请求列表,获取与每个拉取请求关联的提交列表,然后对于每个提交,我想要获取信息,例如提交的作者、与每个提交关联的文件数量以及对每个文件进行的添加和删除次数。我使用 axios 和 github API 来完成此任务。我知道如何使用 API,但 promise 和异步函数使我无法完成任务。我有以下代码:

const axios = require('axios');
var mapOfInformationObjects = new Map();
var listOfCommits = [];
var listOfSHAs = [];
var gitApiPrefix = link I'll use to start fetching data;
var listOfPullRequestDataObjects = [];
var listOfPullRequestNumbers = [];
var mapOfPullNumberToCommits = new Map();

function getAllPullRequests(gitPullRequestApiLink) {
return new Promise((resolve, reject) => {
axios.get(gitPullRequestApiLink).then((response) =>{
listOfPullRequestDataObjects = response['data'];
var k;
for (k = 0; k < listOfPullRequestDataObjects.length; k++){
listOfPullRequestNumbers.push(listOfPullRequestDataObjects[k]['number']);
}
resolve(listOfPullRequestNumbers);
}).catch((error) => {
reject(error);
})
})
}

function getCommitsForEachPullRequestNumber(listOfPRNumbers) {
var j;
for (j = 0; j < listOfPRNumbers.length; j++) {
currPromise = new Promise((resolve, reject) => {
currentGitApiLink = gitApiPrefix + listOfPRNumbers[j] + "/commits";
axios.get(currentGitApiLink).then((response) => {
mapOfPullNumberToCommits.set(listOfPRNumbers[j], response['data']);
resolve("Done with Pull Request Number: " + listOfPRNumbers[j]);
}).catch((error) => {
reject(error);
})
})
}

}

function getListOfCommits(gitCommitApiLink){
return new Promise((resolve, reject) => {
axios.get(gitCommitApiLink).then((response) => {
resolve(response);
}).catch((error) => {
reject(error);
})
})
}

到目前为止,我制作了一些我想顺序调用的函数。首先我想调用 getAllPullRequestNumbers(someLink)然后我想调用 getCommitsForEachPullRequestNumber(listofprnumbers)然后 getListOfCommits(anotherLink)

所以它看起来像

getAllPullRequestNumbers(someLink)
getCommitsForEachPullRequestNumber(listofprnumbers)
getListOfCommits(anotherlink)

但是出现了两个问题:1)我不确定这是否是您调用函数的方式,以便序列中的第一个函数先于另一个函数完成。2)因为我不熟悉Javascript,所以我不确定,尤其是 getCommitsForEachPullRequestNumber 函数,因为你运行一个循环并在循环的每次迭代中调用 axios.get() ,如果这是你在内部处理 promise 的方式功能。

这就是您完成这两项任务的方式吗?任何帮助深表感谢。谢谢!

最佳答案

当您可以同时运行多个异步操作(由 Promise 表示)并且您想知道它们何时全部完成时,您可以使用 Promise.all()。您收集一组 Promise 并将其传递给 Promise.all(),它会告诉您它们何时全部完成或其中一个触发错误。如果全部完成,Promise.all() 将返回一个解析为结果数组的 Promise(每个异步操作对应一个)。

当您迭代一个数组来执行一组异步操作时,最好使用 .map() 因为这可以帮助您创建一个可以提供给的并行的 Promise 数组Promise.all()。以下是在 getCommitsForEachPullRequestNumber() 中执行此操作的方法:

function getCommitsForEachPullRequestNumber(listOfPRNumbers) {
let mapOfPullNumberToCommits = new Map();
return Promise.all(listOfPRNumbers.map(item => {
let currentGitApiLink = gitApiPrefix + item + "/commits";
return axios.get(currentGitApiLink).then(response => {
// put data into the map
mapOfPullNumberToCommits.set(item, response.data);
});
})).then(() => {
// make resolved value be the map we created, now that everything is done
return mapOfPullNumberToCommits;
});
}

// usage:
getCommitsForEachPullRequestNumber(list).then(results => {
console.log(results);
}).catch(err => {
console.log(err);
});

然后,在 getListOfCommits() 中,由于 axios 已经返回了一个 Promise,因此没有理由将其包装在手动创建的 Promise 中。也就是说,事实上,考虑一个 promise 反模式。相反,只需返回 axios 已经返回的 promise 即可。事实上,可能甚至没有理由将其作为函数,因为可以直接使用 axios.get() 来实现相同的结果:

function getListOfCommits(gitCommitApiLink){
return axios.get(gitCommitApiLink);
}

然后,在 getAllPullRequests() 中,您似乎只是执行一次 axios.get() 调用,然后处理结果。可以这样做:

function getAllPullRequests(gitPullRequestApiLink) {
return axios.get(gitPullRequestApiLink).then(response => {
let listOfPullRequestDataObjects = response.data;
return listOfPullRequestDataObjects.map(item => {
return item.number;
});
});
}

现在,如果您尝试按以下顺序依次执行这三个操作:

getAllPullRequests(someLink)
getCommitsForEachPullRequestNumber(listofprnumbers)
getListOfCommits(anotherlink)

您可以将这三个操作的 promise 链接在一起以对它们进行排序:

 getAllPullRequests(someLink)
.then(getCommitsForEachPullRequestNumber)
.then(mapOfPullNumberToCommits => {
// not entirely sure what you want to do here, perhaps
// call getListOfCommits on each item in the map?
}).catch(err => {
console.log(err);
});

或者,如果您将此代码放入 async 函数中,则可以使用 async/awit:

 async function getAllCommits(someLink) {
let pullRequests = await getAllPullRequests(someLink);
let mapOfPullNumberToCommits = await getCommitsForEachPullRequestNumber(pullRequests);
// then use getlistOfCommits() somehow to process mapOfPullNumberToCommits
return finalResults;
}

getAllCommits.then(finalResults => {
console.log(finalResults);
}).catch(err => {
console.log(err);
});

关于Javascript:确保一个异步函数在另一个异步函数完成之前不会运行;带着 promise 工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59009558/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com