我有一个函数,它需要一个数组的GitHub存储库名称,然后我想发送一个请求与每个存储库,获得关于使用的语言在这个存储库的数据,并将其添加到一个数组。它看起来像这样:
function getRepositoryLanguages(owner, repos) {
var stats = [];
repos.forEach(async (repoName) => {
try {
repoLang = await axios.get(
`https://api.github.com/repos/${owner}/${repoName}/languages`,
{
headers: {
Authorization: "token ${token}",
},
}
);
stats.push(repoLang.data, repoName);
} catch (error) {
console.log(error);
}
});
return stats;
}
我想获得每个存储库的语言统计信息,然后将其存储在称为stats
的数组中。问题是这个函数返回一个空数组,当我这样做的时候:
getRepositoryNames(username).then((repos) => {
console.log(getRepositoryLanguages(username, repos));
});
我刚得到一个[]
。
有没有人知道如何正确地编写这个函数,并记住这些函数将在app.get(/stats)
路由中使用?
.forEach
不玩异步行为,它期望一个同步函数(见这里)。
相反,请确保您的getRepositoryLanguages
函数是async
,并使用更简单的迭代器,例如标准的for.. of..
循环。
代码示例如下:
const doSomethingAsync = (repoName) => {
return new Promise(resolve => setTimeout(resolve(repoName+'Lang'), 100));
}
const getRepositoryLanguages = async (owner, repos) => {
let stats = []
for (const repoName of repos) {
const repoLang = await doSomethingAsync(repoName)
stats.push(repoLang)
}
return stats
}
const init = async () => {
const data = await getRepositoryLanguages('username', ['repo1','repo2'])
console.log('data', data)
}
init()
如果你不担心速率限制,并且想并行做一些事情,你可以像这样Promise.all
:
const doSomethingAsync = (repoName) => {
console.log('doSomethingAsync START', repoName)
return new Promise(resolve => setTimeout(() => {
console.log('doSomethingAsync END', repoName)
resolve(repoName + 'Lang')
}, 1000));
}
const getRepositoryLanguages = async(owner, repos) => {
const stats = await Promise.all(repos.map(async(repoName) => {
return doSomethingAsync(repoName)
}))
return stats
}
const init = async() => {
const data = await getRepositoryLanguages('username', ['repo1', 'repo2'])
console.log('data', data)
}
init()
第一条信息:
ForEach 循环不会停止循环的执行,即使其中有async/await操作->将其转换为普通的For Loopfor(let I = 0 ....)
/**
*
* @param owner Owner of repository
* @param repos All his public repos
* @returns Language statistics
*/
async function getRepositoryLanguages(owner, repos) {
/**
* language statistics
*/
let stats = [];
for (let index = 0; index < repos.length; index++) {
const repoName = repos[index];
const response = await axios.get(
`https://api.github.com/repos/${owner}/${repoName}/languages`, {
headers: {
Authorization: "token ${token}",
},
}
)
stats.push({
name: repoName,
languages: response.data
});
};
return stats;
}
getRepositoryNames(username).then(async(repos) => {
console.log(await getRepositoryLanguages(username, repos));
});