除了 Promise.all()
之外,还有以下几种方法可以处理异步并发操作:
Promise.race()
原理
- 如前文所述,
Promise.race()
接受一个包含多个Promise对象的数组作为参数,并行执行这些Promise。一旦数组中有一个Promise的状态变为fulfilled
或rejected
,新返回的Promise就会立即采用该Promise的状态和结果,并结束其他Promise的执行。
示例
const promise1 = new Promise((resolve) => setTimeout(() => resolve('第一个完成'), 2000));
const promise2 = new Promise((resolve) => setTimeout(() => resolve('第二个完成'), 1500));
const promise3 = new Promise((resolve) => setTimeout(() => resolve('第三个完成'), 1000));
Promise.race([promise1, promise2, promise3])
.then((result) => {
console.log('最快的Promise完成,结果为:', result);
})
.catch((error) => {
console.log('有Promise失败,错误为:', error);
});
在上述示例中,promise3
最快完成,所以 Promise.race()
返回的Promise会采用 promise3
的结果,并执行 .then()
方法打印出 第三个完成
。
Promise.any()
原理
Promise.any()
方法也接受一个包含多个Promise对象的数组作为参数,并行执行这些Promise。只要数组中有一个Promise成功变为fulfilled
状态,新返回的Promise就会立即变为fulfilled
,并将该成功的Promise的结果作为最终结果。只有当所有的Promise都变为rejected
状态时,新返回的Promise才会变为rejected
,并将所有Promise的错误信息组成一个数组作为最终的错误原因。
示例
const promiseA = new Promise((resolve, reject) => setTimeout(() => reject('A失败'), 1000));
const promiseB = new Promise((resolve, reject) => setTimeout(() => reject('B失败'), 1500));
const promiseC = new Promise((resolve) => setTimeout(() => resolve('C成功'), 2000));
Promise.any([promiseA, promiseB, promiseC])
.then((result) => {
console.log('至少有一个Promise成功,结果为:', result);
})
.catch((errors) => {
console.log('所有Promise都失败,错误为:', errors);
});
在上述示例中,promiseC
成功,所以 Promise.any()
返回的Promise会采用 promiseC
的结果,并执行 .then()
方法打印出 C成功
。
Promise.allSettled()
原理
Promise.allSettled()
方法同样接受一个包含多个Promise对象的数组作为参数,并行执行这些Promise。它会等待所有的Promise都完成,无论其状态是fulfilled
还是rejected
,然后返回一个包含所有Promise结果和状态的对象数组。每个对象都有status
属性表示Promise的状态,以及value
或reason
属性分别表示成功的值或失败的原因。
示例
const promiseX = new Promise((resolve) => setTimeout(() => resolve('X成功'), 1000));
const promiseY = new Promise((resolve, reject) => setTimeout(() => reject('Y失败'), 1500));
const promiseZ = new Promise((resolve) => setTimeout(() => resolve('Z成功'), 2000));
Promise.allSettled([promiseX, promiseY, promiseZ])
.then((results) => {
console.log('所有Promise都已完成,结果为:', results);
});
上述示例中,Promise.allSettled()
返回的结果是一个包含三个对象的数组,分别对应 promiseX
、promiseY
和 promiseZ
的结果和状态,例如 [{status: 'fulfilled', value: 'X成功'}, {status: 'rejected', reason: 'Y失败'}, {status: 'fulfilled', value: 'Z成功'}]
。
手动实现并发控制
原理
- 通过使用一个计数器和一个数组来手动控制并发的Promise数量。每次执行一个Promise时,计数器加一,当Promise完成时,计数器减一,并将结果存储到数组中。当计数器为零时,表示所有的Promise都已完成,可以对结果数组进行处理。
示例
function concurrentPromises(promises, maxConcurrent) {
let completed = 0;
const results = [];
const promiseArray = Array.from(promises);
return new Promise((resolve, reject) => {
function runNext() {
if (completed === promiseArray.length) {
resolve(results);
return;
}
while (completed < promiseArray.length && maxConcurrent > 0) {
const index = completed;
const promise = promiseArray[index];
maxConcurrent--;
promise
.then((result) => {
results[index] = result;
})
.catch((error) => {
reject(error);
})
.finally(() => {
maxConcurrent++;
completed++;
runNext();
});
}
}
runNext();
});
}
const promises = [
new Promise((resolve) => setTimeout(() => resolve('1'), 1000)),
new Promise((resolve) => setTimeout(() => resolve('2'), 2000)),
new Promise((resolve) => setTimeout(() => resolve('3'), 1500)),
];
concurrentPromises(promises, 2)
.then((result) => {
console.log('手动并发控制完成,结果为:', result);
});
在上述示例中,concurrentPromises
函数接受一个Promise数组和最大并发数作为参数,通过手动控制并发执行的Promise数量,实现了对异步操作的并发控制,并在所有Promise完成后返回结果数组。