你以为 Promise.all() 只能传数组?今天 Firefox 155 用两个方法把这件事彻底原生化了

写过前端的都遇到过这种事:并发请求写成一排,拿到结果按位置解构,突然产品加了一个接口要插到中间——你把数组里对应的位置改好了,结果拿到的是另一个接口的数据,代码悄悄 break 了。这种 bug 最阴的地方在于,它从来不报错,只是数据悄悄错了。

问题出在 Promise.all() 天生的设计:它用数组下标对应结果,顺序一变,解构出来的变量名和真实数据就对不上号。人在重构的时候注意力都在「接口列表顺序有没有改」,没人会去想「数组下标一变,Promise.all() 的结果顺序也跟着变了」。

Firefox 155 今天把这件事彻底原生化了。两个新 API——Promise.allKeyed() 和 Promise.allSettledKeyed(),接受对象而不是数组,返回结果也以对象形式呈现,键名全程跟着你走。

// 以前:位置依赖,重构必踩坑
const [user, posts, recommend] = await Promise.all([
  fetchUser(),
  fetchPosts(),
  fetchRecommend(),
]);
// posts 和 recommend 顺序一旦换位,这里拿到的东西就全乱了

// 现在:命名对应,重构安全
const { user, posts, recommend } = await Promise.allKeyed({
  user: fetchUser(),
  posts: fetchPosts(),
  recommend: fetchRecommend(),
});
// 换顺序?随便换,结果的键名不会变

allSettled 模式也一样,每个键的值是一个 { status: fulfilled | rejected, value | reason } 结构,帮你逐键处理错误而不影响其他请求。

整个设计走 TC39 Await Dictionary 提案,目前 Stage 2.7,Firefox 155 第一个上,Chrome 还在路上,Safari 未表态。生产环境想用的话,core-js 和 es-toolkit 都有 polyfill 可以直接引入。

下一步:如果你的项目里还在用数组 + 位置解构写并发请求,现在就是迁移的窗口——用一个对象字面量替换那个数组,顺便把解构的变量名改成键名,重构安全从此有保障。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 16 阅读