JavaScript中如何正确接收异步函数返回值并存入数组
核心结论
首先直接回答核心疑问:在JS运行环境中,不存在可以同步阻塞获取网络请求这类异步操作返回值的合法可行方案。
JS是单线程事件循环模型,如果你写同步逻辑阻塞主线程等待异步结果,异步请求的回调永远没有机会进入主线程执行,会直接形成死锁,表现为页面/进程完全卡死,也拿不到任何结果。之前遇到的await不生效、Promise一直是pending状态、函数返回undefined,本质都是没有遵循异步代码的编写规则。
问题根因
你当前的简化代码示例里把异步请求当成了同步函数调用,但实际网络请求发起后,JS主线程会立刻继续执行后续代码,不会等待请求返回:
- 你在
final()里调用三个请求函数时,函数内部的请求还没拿到结果,就已经执行到了return逻辑,所以拿到的是undefined - 你在调用
final()后立刻打印variables数组时,三个请求都还在pending状态,数组自然是空的 - 之前写await失效,90%的原因是要么await没有写在async函数内部,要么await的对象不是真正的Promise,要么你在await作用域外部访问结果
正确实现代码
首先改造三个请求函数,确保每个函数返回Promise(用async修饰的函数会自动返回Promise,不需要手动new Promise包装),以fetch请求为例:
// 实际业务里把setTimeout部分替换成你的fetch/axios请求+JSON解析逻辑即可 async function one() { // 模拟1s耗时的接口请求 return new Promise(resolve => setTimeout(() => resolve(1), 1000)) } async function two() { // 模拟2s耗时的接口请求 return new Promise(resolve => setTimeout(() => resolve(2), 2000)) } async function three() { // 模拟0.5s耗时的接口请求 return new Promise(resolve => setTimeout(() => resolve(3), 500)) } const variables = []
根据业务需求选以下两种执行方式即可:
并行请求(性能最优,推荐)
三个接口同时发起请求,等所有接口全部返回后再统一处理,总耗时等于最慢的那个接口的耗时(你的场景里总耗时约2s),接口返回顺序不影响最终数组的顺序:
async function initData() { try { // 并行发起三个请求,等待全部完成 const [res1, res2, res3] = await Promise.all([one(), two(), three()]) variables.push(res1, res2, res3) // 👉 所有依赖variables的逻辑,必须写在await之后 console.log(variables) // 输出 [1,2,3] } catch(err) { // 记得加异常捕获,处理接口请求失败的场景 console.error('请求失败', err) } } initData()
顺序请求(无特殊需求不推荐)
如果业务要求必须等前一个接口返回才能发下一个接口,就逐个await执行,总耗时是三个接口耗时之和(你的场景里总耗时约3.5s):
async function initDataSequential() { try { const a = await one() variables.push(a) const b = await two() variables.push(b) const c = await three() variables.push(c) console.log(variables) // 输出 [1,2,3] } catch(err) { console.error('请求失败', err) } } initDataSequential()
常见踩坑提醒
- 所有依赖异步请求结果的代码,必须写在
await之后,或者写在Promise的.then()回调里,绝对不能在异步函数调用的同步上下文里直接访问结果 - 如果拿到的Promise一直是pending状态,先检查你的Promise内部有没有正确调用
resolve/reject,有没有漏写return导致Promise没有被正确返回 - 不要写while循环轮询变量值的方式等待异步结果,这种写法会阻塞主线程,导致异步回调永远无法执行,直接卡死程序
内容的提问来源于stack exchange,提问作者pallet0
相关产品推荐
相关产品推荐

