手写 promise 方法
Promise.all 原生用法
Promise.all() 方法接收一个 promise 数组作为输入,并返回一个 Promise 实例。当所有 Promise 都成功时,返回的 Promise 状态变为 fulfilled,并且结果是一个包含所有 Promise 结果的数组;如果有任意一个 Promise 失败,则返回的 Promise 状态立即变为 rejected,并且结果是第一个被拒绝的 Promise 的理由。
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, "foo");
});
Promise.all([promise1, promise2, promise3])
.then((values) => {
console.log(values); // [3, 42, "foo"]
})
.catch((error) => {
console.error(error);
});
promiseAll
function promiseAll(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError(`promises must be an array`));
}
let resolvedCounter = 0;
let promiseNum = promises.length;
let resolvedResult = [];
// 如果传入空数组,直接返回空数组结果
if (promiseNum === 0) {
return resolve(resolvedResult);
}
promises.forEach((promise, index) => {
Promise.resolve(promise).then(
(value) => {
resolvedCounter++;
resolvedResult[index] = value;
if (resolvedCounter === promiseNum) {
resolve(resolvedResult);
}
},
(error) => {
reject(error);
}
);
});
});
}
Promise.any 原生用法
Promise.any() 方法接收一个 promise 数组作为输入,并返回一个 Promise 实例。当其中任何一个 Promise 成功时,返回的 Promise 状态变为 fulfilled,并且结果是第一个成功的 Promise 的值;如果所有 Promise 都失败,则返回的 Promise 状态变为 rejected,并返回一个包含所有拒绝原因的 AggregateError。
const promise1 = Promise.reject("error1");
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, "quick"));
const promise3 = new Promise((resolve) => setTimeout(resolve, 500, "slow"));
Promise.any([promise1, promise2, promise3])
.then((value) => {
console.log(value); // 'quick',因为 promise2 最快完成
})
.catch((error) => {
console.error(error); // 当所有 promise 都被拒绝时,这里会收到 AggregateError
});
promiseAny
function promiseAny(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError("promises must be an array"));
}
const length = promises.length;
if (length === 0) {
return reject(new AggregateError([], "All promises were rejected"));
}
let errors = [];
let rejectedCount = 0;
promises.forEach((promise, index) => {
Promise.resolve(promise).then(
(value) => {
resolve(value);
},
(error) => {
errors[index] = error;
rejectedCount++;
if (rejectedCount === length) {
reject(new AggregateError(errors, "All promises were rejected"));
}
}
);
});
});
}
Promise.race 原生用法
Promise.race() 方法接收一个 promise 数组作为输入,并返回一个 Promise 实例。方法返回一个 Promise,一旦迭代器中的某个 promise 解决或拒绝,返回的 promise 就会解决或拒绝。也就是说,返回的 Promise 的状态由第一个完成(无论是成功还是失败)的 Promise 决定。
const promise1 = new Promise((resolve) => setTimeout(resolve, 500, "one"));
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, "two"));
const promise3 = new Promise((resolve, reject) =>
setTimeout(reject, 200, "three")
);
Promise.race([promise1, promise2, promise3])
.then((value) => {
console.log(value); // "two",因为 promise2 最快完成
})
.catch((error) => {
console.error(error);
});
promiseRace
function promiseRace(promises) {
return new Promise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(new TypeError("promises must be an array"));
}
// 空数组会一直pending
promises.forEach((promise) => {
Promise.resolve(promise).then(resolve, reject);
});
});
}
Promise.allSettled 原生用法
Promise.allSettled() 方法接收一个 promise 数组作为输入,并返回一个 Promise 实例。该方法会等待所有 Promise 完成(无论是成功还是失败),然后返回一个包含所有 Promise 结果的数组。数组中的每个元素都是一个对象,包含 status 属性(值为 "fulfilled" 或 "rejected")以及 value(fulfilled 状态下的值)或 reason(rejected 状态下的拒绝原因)属性。
const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) =>
setTimeout(reject, 100, "foo")
);
const promise3 = new Promise((resolve) => setTimeout(resolve, 200, 42));
Promise.allSettled([promise1, promise2, promise3]).then((results) => {
console.log(results);
// [
// { status: 'fulfilled', value: 3 },
// { status: 'rejected', reason: 'foo' },
// { status: 'fulfilled', value: 42 }
// ]
});
promiseAllSettled
function promiseAllSettled(promises) {
return new Promise((resolve) => {
if (!promises || promises.length === 0) {
return resolve([]);
}
const result = [];
let count = 0;
const promiseLength = promises.length;
const processResult = (value, index, status) => {
if (status === "fulfilled") {
result[index] = { status, value };
} else {
result[index] = { status, reason: value };
}
count++;
if (count === promiseLength) {
resolve(result);
}
};
promises.forEach((p, index) => {
Promise.resolve(p).then(
(value) => {
processResult(value, index, "fulfilled");
},
(reason) => {
processResult(reason, index, "rejected");
}
);
});
});
}