前端进阶之旅前端进阶之旅
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
  • 基础篇HTML/CSS/JS 打底
  • 进阶篇原理与工程化
  • 高频篇面试最常问的那批
  • 精选篇按模块收敛的总结
  • 手写篇常考代码手写实现
  • 面经篇真实面试问题复盘
  • AI 篇NEWAI 时代的前端考点
  • 历年面经NEW按年份追踪真实考点
  • 每日一题每天一道,攒手感
  • 专项自测100 题快速查漏
  • 小程序题库小程序专项刷题
  • 算法题库NEW在线编码即时判题
  • 知识卡片NEW碎片时间过考点
  • 面试题大全常见问题解析
  • AI 答疑NEW随时提问,即时解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • AI 定制路线NEW按你的简历现排
  • AI 知识地图NEW串起全站知识点
  • 原理篇React / Vue 源码拆解
  • HTTP从报文一路讲到 HTTPS
  • 浏览器渲染、事件循环、进程
  • 计算机基础Linux、网络、操作系统
  • 设计模式23 种模式怎么用
  • Node学习指南从环境搭建到服务端
  • NPM工作流script、依赖与发布
  • Docker容器化部署上手
  • Canvas图形与动画实战
  • 前端系统进阶学习大型项目工程化
  • 前端综合文章长期沉淀的实践文
  • 思维导图知识点全景图
  • 学习路线按图索骥不跑偏
  • AI 热点NEWAI 每日动态
  • 公众号动态公众号历史文章
  • 博客动态站长的技术博客
  • 开发者导航常用工具与文档站
首页程序员面试题库Promise.all 空数组
JSJavaScript异步与 Promise

Promise.all 传入空数组时,会怎样?

Promise.all([]) 返回一个已经 fulfilled 的 Promise,其值是一个空数组[]。它不会永久pending,也不会报错,回调仍被调度到微任务队列异步执行。

前端进阶之旅 · 一题精讲更新于 2026.09.05
JavaScript#异步与 Promise#异步编程
先看核心答案读代码示例
理解线索

空输入视为已完成聚合

  1. 状态置为fulfilled空列表没有未决对象,满足全部条件
  2. 兑现值为[]结果保留数组形态,空集合同样返回[]
  3. 回调仍异步状态已定,但微任务调度不变

仅空可迭代对象触发同步完成,非空但全已解决时仍异步

核心回答

先记住这个答案

Promise.all([]) 会立即得到一个状态为 fulfilled 的 Promise,兑现值为 []。规范把“全部成功”扩展到零个任务的情形,因此不需要等待即可完成。虽然内部通常同步进入 fulfilled 状态,但通过 then 注册的处理器仍按微任务异步执行,所以同步代码之后才看到回调,返回值可直接用于需要数组的下游逻辑。

  • 返回已 fulfilled 的 Promise,值为空数组[]
  • 不会 pending 或 reject,成功聚合零个结果
  • then 回调仍异步,不能同步取到值

空输入下的状态派生规则

Promise.all 的语义是等待一个 iterable 中所有 Promise 都成功,随后把每个结果按序放入数组。当 iterable 是空时,集合不存在任何元素,因此“所有成功”这一前置条件立即为真。ECMAScript 规范明确此情况下返回的 Promise 为 fulfilled,其 value 就是空数组 []。否则会出现一个永久 pending 的聚合体,让调用方无法继续。

从引擎处理顺序看,Promise.all([]) 在内部初始化过程会创建聚合 Promise,但空列表使它在同一回合内就进入 fulfilled 状态。不过这不意味着 .then 回调会同步执行——Promise 的 reaction 任务总是排队到微任务队列。以下代码验证了:同步日志先输出,然后才看到 then 的内容。

空数组的异步回调验证JavaScript
console.log('start');
Promise.all([]).then(values => console.log(JSON.stringify(values)));
console.log('end');
查看输出与解释
start
end
[]

先打印 start 和 end,随后微任务队列中执行 then,打印 [],说明 Promise 已经 fulfilled 但没有同步执行 then。

动态任务列表为空时的统一出口

假设一个批量数据预加载函数,它接收一组由用户选中的条目 id,为每个 id 发起一个异步加载任务,并用 Promise.all 合并结果。当用户一个都没勾选时,ids 数组为空。此时若把空列表直接交给 Promise.all,会得到 [],后续代码可以自然地将“加载完成”状态推进,不会卡在加载中或进入错误分支。

这个场景说明 Promise.all 的空数组处理是组合器的统一出口。你不需要在调用前单独判断 if (ids.length === 0) return Promise.resolve([]),动态生成的任务列表即使为空也能走同一套聚合逻辑。代价是结果 [] 并不代表有任何数据,仅表示没有失败项,下游必须对空结果做语义上的区分。

容易失效的使用边界

容易失效的条件之一是将空数组与“没有任何任务”混为一谈。虽然返回值总是 fulfilled,但如果后续逻辑期望数组里至少有一项,就会静默产生空结果,甚至掩盖之前任务来源为空或配置错误。另一种失效是尝试将 null 或 undefined 交给 Promise.all——它们不可迭代,会直接抛出 TypeError,与空数组的合法行为不同。

另一个边界是空数组只使 Promise.all 本身同步 fulfil,任何基于该 Promise 的后续处理仍要经过微任务排队。如果你在同一个调用栈里依赖它之后立即执行操作,必须用 await 或 then 接续。此外,空数组与只含非 Promise 值的数组不同:后者在所有输入都已是 resolve 时仍会等待至少一个微任务才 fulfilled,而空数组的状态提前确定。

回答前,多想一步

容易答错的地方

认为会永久 pending 或报错
有些开发者以为没有输入就无法完成,实际上规范把空集合视为“所有成功”的真空情形,返回已 fulfilled 的 Promise,value 是 []。因此不会 pending,也不会因空数组抛出异常。
认为 then 会同步执行
即使 Promise.all([]) 状态立即为 fulfilled,通过 then 注册的回调也总是异步进入微任务队列。同步代码执行完毕后回调才触发,这是 Promise 的基本调度规则,不因空输入而改变。
试着用自己的话回答

面试官还会怎么问?

Promise.all([]) 与 Promise.resolve([]) 有什么本质区别?

两者最终都产生一个 fulfilled 且值为 [] 的 Promise,时序上 then 也都走微任务,几乎没有可观测差异。但语义不同:Promise.all([]) 表达“零个异步任务均已成功”,适合组合器统一处理;Promise.resolve([]) 表示直接构造一个成功 Promise,不必经过聚合。

Promise.all 传入非 Promise 的原始值数组时会怎样?

例如 Promise.all([1,2,3]),每个值都会被当作已解决的成功项,整体返回的 Promise 最终 fulfilled 且值为 [1,2,3]。但它是异步完成的,初始呈 pending,不像空数组那样同步 fulfil,因为非空输入需要走一轮微任务调度。

空数组会触发 unhandledrejection 吗?

不会。空数组没有任何输入 promise,自然也不存在拒绝来源,因此不会产生未处理的拒绝事件。但如果你后续在这个组合结果上链接 rejection 处理器并抛出异常,则与空数组无关。

从一道题,走向一组知识

把知识连起来

异步与 Promise

Promise.all 的输入数组中如果存在非 Promise 值,会如何处理?

同属「异步与 Promise」专题,接着看 Promise.all 非 Promise 值 在具体场景中的处理方式。

异步与 Promise

Promise.all 在其中一个 Promise 被拒绝时,会立即拒绝吗?其他 Promise 的结果如何处理?

同属「异步与 Promise」专题,接着看 Promise.all 快速失败 在具体场景中的处理方式。

异步与 Promise

Promise.resolve 传入一个 thenable 对象时会发生什么?

同属「异步与 Promise」专题,接着看 Promise.resolve thenable 在具体场景中的处理方式。

放回知识体系中复习JavaScript 进阶知识

参考资料

  • Promise.all()

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 空输入下的状态派生规则
  3. 动态任务列表为空时的统一出口
  4. 容易失效的使用边界
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑