如何在Express JS异步函数中等待Promise.all解析完成后再返回值
解决Promise.all返回undefined数组的问题
嘿,你猜得完全没错!问题确实出在异步操作的返回时机和Promise链的处理上。咱们来一步步拆解问题,然后修复它:
问题根源
你在repos.map里的async函数中,调用了fetch但没有把这个Promise链返回出去。虽然你在.then回调里写了return await repo,但这个return只属于那个内部的回调函数,外层的async函数并没有拿到这个返回值,所以map生成的每个Promise都默认resolve成了undefined,最终Promise.all解析后自然就是全是undefined的数组。
修复方案
有两种清晰的修复方式,选你觉得顺手的就行:
方式1:返回整个fetch的Promise链
只需要在fetch前面加个return,让外层的async函数把这个Promise暴露给Promise.all:
const getGitHubCommits = async (username, repos) => { try { const repositories = await Promise.all( repos.map(async (repo) => { // 关键:返回fetch的Promise链 return fetch(`https://api.github.com/repos/${username}/${repo.name}/commits?per_page=5`) .then(response => response.json()) .then(response => { repo.commits = response.slice(0, 5) console.log(repo) return repo }) }) ); console.log(repositories) return repositories } catch (error) { console.log(error) return "No commits found" } }
方式2:用await替代.then(更推荐,代码更易读)
既然已经用了async函数,不如全程用await来处理异步,避免嵌套的.then,也不容易遗漏返回:
const getGitHubCommits = async (username, repos) => { try { const repositories = await Promise.all( repos.map(async (repo) => { // 用await处理fetch和json解析 const response = await fetch(`https://api.github.com/repos/${username}/${repo.name}/commits?per_page=5`) const commits = await response.json() repo.commits = commits.slice(0, 5) console.log(repo) return repo }) ); console.log(repositories) return repositories } catch (error) { console.log(error) return "No commits found" } }
为什么这样能解决问题?
修正后,repos.map生成的每个元素都是一个Promise,这个Promise会在fetch请求完成并处理完commits后,resolve为带commits属性的repo对象。Promise.all会等待所有这些Promise都resolve,最终拿到的就是你想要的仓库数组啦。
内容的提问来源于stack exchange,提问作者PanzerMoonbeam
相关产品推荐
相关产品推荐

