You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

存储异步Promise后无法访问已解析值的技术问题

问题描述

我尝试把未决Promise作为对象的值存储,等待其解析后再调用,步骤如下:

let names = ["aaron", "bob", "john", "aaron"];
let allNames = {};

// 以名称为键初始化对象

names.forEach(name => {
   if (!allNames[name]) {
         allNames[name] = null;
   }
});

// 并行执行异步请求,将未决Promise存储为对象值

let allDataForNamedPerson;

for (const [x] of names) {
   if (!allNames[name]) {
       allDataForNamesPerson = this.getNameData(name)// 异步API调用
       
       allNames[name] = allDataForNamesPerson // 存储Promise
   }
}

随后等待所有Promise解析:

await Promise.all([...Object.values(this.allNames)]);

问题是,当我从对象中查找已解析的值(例如allNames["john"])时,控制台显示该值是一个包裹着对象的Promise:

promise {
   salary: 41992,
   position: clerk
}

因此无法通过allNames["john"].salary访问属性,返回undefined。请问我哪里出错了?


问题分析与解决

错误1:循环变量处理逻辑错误

你在for (const [x] of names)这一行犯了解构错误:names是字符串数组,并非键值对数组,[x]会取每个字符串的第一个字符,且后续代码里使用的name变量未在循环中定义,这会导致逻辑混乱,甚至无法正确调用异步API。

正确的遍历方式应为直接获取数组元素:

for (const name of names) {

错误2:未将Promise解析值替换回原对象

Promise.all仅会等待所有Promise完成并返回包含所有解析结果的数组,但不会自动把allNames对象中的Promise替换成解析后的值。因此即使await执行完毕,allNames里存储的依然是Promise对象,自然无法直接访问salary这类属性。

修正后的完整代码

let names = ["aaron", "bob", "john", "aaron"];
let allNames = {};

// 初始化对象并直接存储Promise,避免重复请求
names.forEach(name => {
   if (!allNames[name]) {
         allNames[name] = this.getNameData(name);
   }
});

// 等待所有Promise完成,获取解析结果数组
const resolvedValues = await Promise.all(Object.values(allNames));

// 将解析结果对应回原对象的键
Object.keys(allNames).forEach((key, index) => {
  allNames[key] = resolvedValues[index];
});

// 现在可直接访问属性
console.log(allNames["john"].salary);

额外优化

可以合并初始化与存储Promise的步骤,无需先将值设为null再替换,第一次遇到名称时直接存储Promise即可,减少多余判断。

内容的提问来源于stack exchange,提问作者sal3jfc

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 09:27:28