JavaScript 面试题
目录

手动实现一个 Promise.all。

· 约 4 分钟读完 · 第 116 / 507 章

推荐答案

本题详细解读

核心概念

Promise.all 的核心在于并发处理多个 Promise,并在所有 Promise 都成功 resolve 时返回一个包含所有结果的 Promise。如果其中任何一个 Promise 失败 reject,则 Promise.all 返回的 Promise 也会立即 reject。

实现步骤

  1. 接收参数: Promise.myAll 接收一个 Promise 数组 promises 作为参数。
  2. 返回 Promise: 返回一个新的 Promise,该 Promise 的状态将根据所有输入 Promise 的状态而定。
  3. 空数组处理: 如果 promises 为空或不存在,则立即 resolve 一个空数组。
  4. 初始化: 初始化一个用于存储所有 resolve 结果的 results 数组,以及一个计数器 resolvedCount 来记录已 resolve 的 Promise 数量。
  5. 遍历 Promise 数组: 遍历 promises 数组。
    • 使用 Promise.resolve 包装每个数组元素,确保即使元素不是 Promise ,也能统一处理。
    • 对每一个 Promise 调用 .then 方法
    • 在 .then 的 resolve 回调中:
      • 将 resolve 的值按顺序存储到 results 数组的相应位置。
      • resolvedCount 加一。
      • 检查 resolvedCount 是否等于 totalPromises,如果是,则说明所有 Promise 都 resolve 了,调用外部 Promise 的 resolve 并传入 results 数组。
    • 在 .then 的 reject 回调中:
      • 调用外部 Promise 的 reject,并将 reject 的原因传递出去。
  6. 错误处理: 如果任何一个 Promise 失败 (reject),则立即 reject 整个 Promise.all 返回的 Promise,并传递 reject 的原因。

关键点

  • 并发处理: Promise.all 需要并发处理所有的 Promise,而不是顺序处理,所以不能使用async await。
  • 顺序返回: 返回的数组顺序需要和传入的顺序保持一致。
  • 短路效应: 只要有一个 Promise reject,整个 Promise.all 都会 reject,这就是短路效应。
  • 非 Promise 值处理: 输入的 promises 数组中可能包含非 Promise 的值,所以需要使用 Promise.resolve 包装,将其转换为 Promise。
  • 空数组处理: 当 promises 为空时,应该立即 resolve 一个空数组。
  • 错误处理: 需要正确捕获并传递 Promise 的错误。