以逻辑门角度深入理解promise组合方法

19 阅读5分钟

在数字电路设计中,逻辑门是构建复杂系统的基础元件。同样,在现代 JavaScript 异步编程中,Promise 的组合方法(allallSettledanyrace)构成了异步流程控制的基础电路。
本文将深入探讨这些方法的行为模式,通过逻辑门比喻建立直观理解,并帮助你彻底掌握 Promise 的组合方法——甚至推演出新的或者你未发现的异步控制模式。


核心概念定义

我们先建立统一的逻辑系统:

  • Promise 状态映射
    • Fulfilled (1):成功,异步操作完成并返回结果
    • Rejected (0):失败,异步操作抛出错误
  • 输入向量:一个 Promise 数组,每个 Promise 是一个输入信号
  • 输出:一个新的 Promise,其状态由输入向量的状态组合决定

状态常量

const PENDING = "pending";
const FULFILLED = "fulfilled";  
const REJECTED = "rejected";     

1️.Promise.all():逻辑与门(AND Gate)

// 逻辑表达式: OUTPUT = INPUT₁ ∧ INPUT₂ ∧ ... ∧ INPUTₙ
// 所有输入为 1 时,输出为 1;任一输入为 0 时,输出为 0

逻辑门类比

  • AND 门特性:全高电平 → 高电平;任一低电平 → 低电平
  • 对应行为:所有 Promise 成功才成功,任一失败立即失败
  • 典型场景:多个依赖接口必须全部加载成功(如用户资料 + 权限 + 配置)

真值表

Promise₁Promise₂Promise.all解释
1 (成功)1 (成功)1 (成功)全部成功
1 (成功)0 (失败)0 (失败)快速失败
0 (失败)1 (成功)0 (失败)快速失败
0 (失败)0 (失败)0 (失败)快速失败

特性

  1. 快速失败:第一个 reject 立即 reject 整体
  2. 顺序结果:成功时按输入顺序返回值数组
  3. 短路求值:失败后不再等待其他 Promise

实现

Promise.myAll = function (iterable) {
  if (iterable == null || typeof iterable[Symbol.iterator] !== "function") {
    return Promise.reject(new TypeError("Argument is not iterable"));
  }

  const promises = Array.from(iterable);
  if (promises.length === 0) return Promise.resolve([]);

  return new Promise((resolve, reject) => {
    const result = new Array(promises.length);
    let settledCount = 0;

    promises.forEach((item, index) => {
      Promise.resolve(item)
        .then(value => {
          result[index] = value;
          settledCount++;
          if (settledCount === promises.length) resolve(result);
        })
        .catch(reject); // 任一失败,整体失败
    });
  });
};

2. Promise.any():逻辑或门(OR Gate)

// 逻辑表达式: OUTPUT = INPUT₁ ∨ INPUT₂ ∨ ... ∨ INPUTₙ
// 任一输入为 1 时,输出为 1;所有输入为 0 时,输出为 0

逻辑门类比

  • OR 门特性:任一高电平 → 高电平;全低电平 → 低电平
  • 对应行为:任一 Promise 成功即成功,全部失败才失败
  • 典型场景:多 CDN 加载资源,取最快成功的响应

真值表

Promise₁Promise₂Promise.any解释
1 (成功)1 (成功)1 (成功)任一成功即可
1 (成功)0 (失败)1 (成功)任一成功即可
0 (失败)1 (成功)1 (成功)任一成功即可
0 (失败)0 (失败)0 (失败)全部失败

特性

  1. 快速成功:第一个 fulfill 立即 resolve 整体
  2. AggregateError:全部失败时,聚合所有错误
  3. 乐观策略:优先寻找成功路径

实现

Promise.myAny = function (iterable) {
  if (iterable == null || typeof iterable[Symbol.iterator] !== "function") {
    return Promise.reject(new TypeError("Argument is not iterable"));
  }

  const promises = Array.from(iterable);
  if (promises.length === 0) {
    return Promise.reject(
      new AggregateError([], "All promises were rejected")
    );
  }

  return new Promise((resolve, reject) => {
    const errors = new Array(promises.length);
    let settledCount = 0;
    let resolved = false;

    promises.forEach((item, index) => {
      Promise.resolve(item)
        .then(value => {
          if (!resolved) {
            resolved = true;
            resolve(value); // 第一个成功即返回
          }
        })
        .catch(reason => {
          errors[index] = reason;
          settledCount++;
          if (settledCount === promises.length && !resolved) {
            reject(new AggregateError(errors, "All promises were rejected"));
          }
        });
    });
  });
};

3️.Promise.race():选择器 / 锁存器(Selector / Latch)

// 逻辑表达式: OUTPUT = FIRST_SETTLED(INPUT₁, INPUT₂, ..., INPUTₙ)
// 输出等于第一个 settled(fulfilled 或 rejected)的输入

逻辑门类比

  • 选择器特性:捕获第一个变化的信号
  • 对应行为:谁先 settle(无论成功/失败),谁决定结果
  • 典型场景:超时控制、竞态请求、最快响应获取

行为表

第一个 settled结果说明
fulfilled成功返回其值
rejected失败抛出其错误

特性

  1. 赢家通吃:第一个 settle 的 Promise 决定一切
  2. 忽略后续:其余 Promise 被丢弃(但仍在后台运行)
  3. 非确定性:结果取决于执行时序

实现

Promise.myRace = function (iterable) {
  if (iterable == null || typeof iterable[Symbol.iterator] !== "function") {
    return Promise.reject(new TypeError("Argument is not iterable"));
  }

  const promises = Array.from(iterable);
  // 规范:Promise.race([]) 永远 pending
  if (promises.length === 0) {
    return new Promise(() => {}); // 永不 settle
  }

  return new Promise((resolve, reject) => {
    promises.forEach(item => {
      Promise.resolve(item).then(resolve, reject);
    });
  });
};

4️.Promise.allSettled():状态收集器(State Collector)

// 逻辑表达式: OUTPUT = COLLECT(STATUS(INPUT₁), ..., STATUS(INPUTₙ))
// 收集所有 Promise 的最终状态,永不 reject

逻辑门类比

  • 状态寄存器:记录每一位的最终状态,不做逻辑运算
  • 对应行为:等待所有 Promise settle,返回完整状态快照
  • 典型场景:批量任务日志、结果分析、容错汇总

输出

// 成功
{ status: 'fulfilled', value: result }

// 失败
{ status: 'rejected', reason: error } 

特性

  1. 永不失败:返回的 Promise 总是 fulfilled
  2. 完整诊断:每个 Promise 的状态和数据都可追溯
  3. 无短路:必须等所有 Promise settle

规范

Promise.myAllSettled = function (iterable) {
  if (iterable == null || typeof iterable[Symbol.iterator] !== "function") {
    return Promise.reject(new TypeError("Argument is not iterable"));
  }

  const promises = Array.from(iterable);
  if (promises.length === 0) return Promise.resolve([]);

  return new Promise(resolve => {
    const result = new Array(promises.length);
    let completedCount = 0;

    promises.forEach((item, index) => {
      Promise.resolve(item)
        .then(
          value => {
            result[index] = { status: FULFILLED, value };
          },
          reason => {
            result[index] = { status: REJECTED, reason }; 
          }
        )
        .finally(() => {
          completedCount++;
          if (completedCount === promises.length) resolve(result);
        });
    });
  });
};

四方法对比矩阵

方法逻辑类比成功条件失败条件输出类型是否短路
Promise.allAND 门全部成功任一失败值数组✅(失败)
Promise.anyOR 门任一成功全部失败单个值✅(成功)
Promise.race选择器第一个成功第一个失败单个值
Promise.allSettled状态寄存器总是成功永不失败状态对象数组

高级组合模式(异步“组合电路”)

1. 带超时的 AND 运算

function allWithTimeout(promises, timeoutMs) {
  return Promise.race([
    Promise.all(promises),
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error('Timeout')), timeoutMs)
    )
  ]);
}
// 电路:AND 门 + 超时选择器

2. 多数表决电路(Majority Vote)

function majority(promises) {
  return Promise.allSettled(promises).then(results => {
    const successes = results.filter(r => r.status === 'fulfilled');
    const failures = results.filter(r => r.status === 'rejected');

    if (successes.length > failures.length) {
      return successes.map(s => s.value);
    } else {
      throw new AggregateError(
        failures.map(f => f.reason),
        'Majority of promises rejected'
      );
    }
  });
}
// 电路:状态寄存器 + 比较器 + 选择器

3. 优先级仲裁器(顺序尝试)

async function priorityArbitrator(promiseFactories) {
  for (const factory of promiseFactories) {
    try {
      return await factory();
    } catch {
      continue; // 尝试下一个
    }
  }
  throw new Error('All attempts failed');
}
// 电路:优先级编码器 + OR 门

通过逻辑门视角理解 Promise 组合方法,我们能:

  1. 建立直觉模型:将抽象异步流映射到熟悉电路概念
  2. 预测行为:像分析真值表一样推理复杂异步逻辑
  3. 设计新模式:借鉴电路设计思想构建自定义控制流
  4. 调试优化:识别“短路点”、“竞争条件”、“状态丢失”等问题