| 方法 | 输入 | 输出 | 典型场景 |
|---|---|---|---|
Promise.all |
多个 Promise | 所有成功 -> 结果数组;任一失败 -> 立即 reject | 多个独立请求,需要全部结果 |
Promise.race |
多个 Promise | 最先 settled 的结果(成功或失败) | 超时控制、请求竞速 |
Promise.any |
多个 Promise | 任一成功 -> 该成功值;全部失败 -> AggregateError | 多个备用接口,取最快成功的 |
核心逻辑:
Promise.resolve 包一层(支持非 promise 值)Promise.myAll = function(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('Argument must be an array'));
}
const results = [];
let completed = 0;
const total = promises.length;
if (total === 0) {
return resolve(results);
}
promises.forEach((p, index) => {
Promise.resolve(p).then(
(value) => {
results[index] = value;
completed++;
if (completed === total) {
resolve(results);
}
},
(reason) => {
reject(reason);
}
);
});
});
};
测试:
const p1 = Promise.resolve(1);
const p2 = 2;
const p3 = new Promise((res) => setTimeout(() => res(3), 100));
Promise.myAll([p1, p2, p3]).then(console.log); // [1, 2, 3](约100ms后)
核心逻辑:谁先 settled(成功或失败),就 resolve/reject 谁。
Promise.myRace = function(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('Argument must be an array'));
}
promises.forEach((p) => {
Promise.resolve(p).then(resolve, reject);
});
});
};
测试:
const slow = new Promise(res => setTimeout(() => res('慢'), 100));
const fast = new Promise(res => setTimeout(() => res('快'), 20));
Promise.myRace([slow, fast]).then(console.log); // '快'
核心逻辑:
AggregateError
Promise.myAny = function(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError('Argument must be an array'));
}
const errors = [];
let rejectedCount = 0;
const total = promises.length;
if (total === 0) {
return reject(new AggregateError([], 'All promises were rejected'));
}
promises.forEach((p, index) => {
Promise.resolve(p).then(
(value) => {
resolve(value);
},
(reason) => {
errors[index] = reason;
rejectedCount++;
if (rejectedCount === total) {
reject(new AggregateError(errors, 'All promises were rejected'));
}
}
);
});
});
};
测试:
const p1 = Promise.reject('错误1');
const p2 = new Promise(res => setTimeout(() => res('成功'), 50));
const p3 = Promise.reject('错误3');
Promise.myAny([p1, p2, p3]).then(console.log); // '成功'(50ms后)
Promise.all([]) → 立即 resolve []
Promise.race([]) → 永远 pending(不会 resolve/reject)Promise.any([]) → 立即 reject AggregateError
我们的实现已正确处理。
Promise.resolve 自动包装,无需额外处理。
不影响逻辑,依然按顺序等待或竞速。
// Promise.all
Promise.myAll = function(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) reject(new TypeError('Expected array'));
const results = [];
let completed = 0;
if (promises.length === 0) resolve(results);
promises.forEach((p, i) => {
Promise.resolve(p).then(
v => { results[i] = v; completed++; if (completed === promises.length) resolve(results); },
e => reject(e)
);
});
});
};
// Promise.race
Promise.myRace = function(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) reject(new TypeError('Expected array'));
promises.forEach(p => Promise.resolve(p).then(resolve, reject));
});
};
// Promise.any
Promise.myAny = function(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) reject(new TypeError('Expected array'));
const errors = [];
let rejected = 0;
if (promises.length === 0) reject(new AggregateError([], 'All rejected'));
promises.forEach((p, i) => {
Promise.resolve(p).then(
v => resolve(v),
e => { errors[i] = e; rejected++; if (rejected === promises.length) reject(new AggregateError(errors, 'All rejected')); }
);
});
});
};
Promise.all:全成功才成功,一失败就失败Promise.race:谁先 settled 就输出谁Promise.any:一成功就成功,全失败才失败文中代码已测试,可用于生产环境 polyfill。下一篇写
Promise.allSettled和Promise.withResolvers。
讨论:你在项目中用过 Promise.any 吗?一般用在哪里?欢迎评论区分享。