在数字电路设计中,逻辑门是构建复杂系统的基础元件。同样,在现代 JavaScript 异步编程中,Promise 的组合方法(all、allSettled、any、race)构成了异步流程控制的基础电路。
本文将深入探讨这些方法的行为模式,通过逻辑门比喻建立直观理解,并帮助你彻底掌握 Promise 的组合方法——甚至推演出新的或者你未发现的异步控制模式。
核心概念定义
我们先建立统一的逻辑系统:
- Promise 状态映射:
- Fulfilled (1):成功,异步操作完成并返回结果
- Rejected (0):失败,异步操作抛出错误
- 输入向量:一个 Promise 数组,每个 Promise 是一个输入信号
- 输出:一个新的 Promise,其状态由输入向量的状态组合决定
状态常量
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
1️.Promise.all():逻辑与门(AND Gate)
逻辑门类比
- AND 门特性:全高电平 → 高电平;任一低电平 → 低电平
- 对应行为:所有 Promise 成功才成功,任一失败立即失败
- 典型场景:多个依赖接口必须全部加载成功(如用户资料 + 权限 + 配置)
真值表
| Promise₁ | Promise₂ | Promise.all | 解释 |
|---|
| 1 (成功) | 1 (成功) | 1 (成功) | 全部成功 |
| 1 (成功) | 0 (失败) | 0 (失败) | 快速失败 |
| 0 (失败) | 1 (成功) | 0 (失败) | 快速失败 |
| 0 (失败) | 0 (失败) | 0 (失败) | 快速失败 |
特性
- 快速失败:第一个 reject 立即 reject 整体
- 顺序结果:成功时按输入顺序返回值数组
- 短路求值:失败后不再等待其他 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)
逻辑门类比
- OR 门特性:任一高电平 → 高电平;全低电平 → 低电平
- 对应行为:任一 Promise 成功即成功,全部失败才失败
- 典型场景:多 CDN 加载资源,取最快成功的响应
真值表
| Promise₁ | Promise₂ | Promise.any | 解释 |
|---|
| 1 (成功) | 1 (成功) | 1 (成功) | 任一成功即可 |
| 1 (成功) | 0 (失败) | 1 (成功) | 任一成功即可 |
| 0 (失败) | 1 (成功) | 1 (成功) | 任一成功即可 |
| 0 (失败) | 0 (失败) | 0 (失败) | 全部失败 |
特性
- 快速成功:第一个 fulfill 立即 resolve 整体
- AggregateError:全部失败时,聚合所有错误
- 乐观策略:优先寻找成功路径
实现
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)
逻辑门类比
- 选择器特性:捕获第一个变化的信号
- 对应行为:谁先 settle(无论成功/失败),谁决定结果
- 典型场景:超时控制、竞态请求、最快响应获取
行为表
| 第一个 settled | 结果 | 说明 |
|---|
| fulfilled | 成功 | 返回其值 |
| rejected | 失败 | 抛出其错误 |
特性
- 赢家通吃:第一个 settle 的 Promise 决定一切
- 忽略后续:其余 Promise 被丢弃(但仍在后台运行)
- 非确定性:结果取决于执行时序
实现
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);
if (promises.length === 0) {
return new Promise(() => {});
}
return new Promise((resolve, reject) => {
promises.forEach(item => {
Promise.resolve(item).then(resolve, reject);
});
});
};
4️.Promise.allSettled():状态收集器(State Collector)
逻辑门类比
- 状态寄存器:记录每一位的最终状态,不做逻辑运算
- 对应行为:等待所有 Promise settle,返回完整状态快照
- 典型场景:批量任务日志、结果分析、容错汇总
输出
{ status: 'fulfilled', value: result }
{ status: 'rejected', reason: error }
特性
- 永不失败:返回的 Promise 总是 fulfilled
- 完整诊断:每个 Promise 的状态和数据都可追溯
- 无短路:必须等所有 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.all | AND 门 | 全部成功 | 任一失败 | 值数组 | ✅(失败) |
Promise.any | OR 门 | 任一成功 | 全部失败 | 单个值 | ✅(成功) |
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)
)
]);
}
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');
}
通过逻辑门视角理解 Promise 组合方法,我们能:
- 建立直觉模型:将抽象异步流映射到熟悉电路概念
- 预测行为:像分析真值表一样推理复杂异步逻辑
- 设计新模式:借鉴电路设计思想构建自定义控制流
- 调试优化:识别“短路点”、“竞争条件”、“状态丢失”等问题