// 若原生 Promise 不包含 .race 方法,则将其添加
if (typeof Promise.prototype.race !== 'function') {
Promise.race = function(promises) {
if (!Array.isArray(promises)) {
if (promises[Symbol.iterator]) {
promises = Array.from(promises);
} else {
throw new TypeError('Promise.race expects an array or iterable object');
}
}
return new Promise((resolve, reject) => {
// 遍历传入的 Promise 数组
for (let i = 0; i < promises.length; i++) {
// 无论传入的 p 是否已经是 Promise,都要使用 Promise.resolve 包装
Promise.resolve(promises[i]).then(
// 成功回调,解决外部的 Promise 并传递结果
value => {
// 一旦有 Promise 被解决,立刻解决外部的 Promise
resolve(value);
// 阻止后续 Promises 的回调继续执行
promises = [];
},
// 失败回调,拒绝外部的 Promise 并传递失败原因
reason => {
// 一旦有 Promise 被拒绝,立刻拒绝外部的 Promise
reject(reason);
// 同样阻止后续 Promises 的回调继续执行
promises = [];
}
);
}
// 特殊处理:如果传入的 promises 数组为空
if (promises.length === 0) {
// 返回一个永远不解决也不拒绝的 Promise,这并不符合 Promise.race 的语义,
// 在实际实现中,Promise.race([]) 应该返回一个永远不解决的 Promise
// 但在这种情况下,我们可以选择返回一个状态为 pending 的 Promise,或者抛出错误。
// 由于实际情况应该根据具体需求和规范而定,这里暂时不做处理。
}
});
};
}
// 示例:
const promises = [
fetch('https://api.example.com/fast-response'),
fetch('https://api.example.com/slow-response'),
];
Promise.race(promises)
.then(response => {
console.log('The fastest request succeeded:');
response.json().then(data => console.log(data));
})
.catch(reason => console.error('The first failed request:', reason));
Promise.race 会返回一个新的 Promise,当传入数组中的任意一个 Promise 被解决或拒绝时,新的 Promise 也会立刻以相同的值(解决或拒绝)进行相应状态的改变。这意味着第一个解决或拒绝的 Promise 的结果将决定 Promise.race 返回的 Promise 的结果。如果传入的是空数组,在真实环境中,返回的 Promise 应该是一个永远不会解决的 Promise,但是在这里为了简洁起见,我们没有特殊处理空数组的情况。