Promise.all 内部实现机制
- 处理多个 Promise 状态变化:
Promise.all
接受一个 Promise 数组作为参数(也可以是包含 then 方法的类似数组的对象)。
- 它会创建一个新的 Promise。这个新 Promise 的状态取决于传入的所有 Promise 的状态。
- 当所有传入的 Promise 都变为
resolved
时,新 Promise 才会 resolved
,并且其 resolved
的值是一个数组,该数组按顺序包含了所有传入 Promise resolved
的值。
- 如果其中任何一个 Promise 变为
rejected
,新 Promise 就会立即 rejected
,其 rejected
的原因就是第一个变为 rejected
的 Promise 的原因。
- 事件循环中的执行逻辑:
Promise.all
是异步操作,不会阻塞事件循环。当调用 Promise.all
时,它会立即返回一个处于 pending
状态的新 Promise。
- 然后,它会依次执行传入的每个 Promise。这些 Promise 的执行是异步的,会被放入微任务队列。
- 当所有 Promise 都完成(
resolved
或 rejected
)后,根据上述规则,Promise.all
返回的新 Promise 会相应地变为 resolved
或 rejected
,并将其结果放入微任务队列,等待当前宏任务执行完毕后,在微任务阶段执行。
Promise.race 内部实现机制
- 处理多个 Promise 状态变化:
Promise.race
同样接受一个 Promise 数组(或类似数组对象)作为参数。
- 它也返回一个新的 Promise。这个新 Promise 的状态会随着传入的 Promise 数组中第一个完成(
resolved
或 rejected
)的 Promise 而改变。
- 也就是说,只要有一个 Promise 完成,
Promise.race
返回的新 Promise 就会以相同的状态和值(或原因)完成。
- 事件循环中的执行逻辑:
Promise.race
也是异步操作,立即返回一个 pending
状态的新 Promise。
- 然后,它会并行执行传入的所有 Promise,这些 Promise 的执行被放入微任务队列。
- 当第一个 Promise 完成时,
Promise.race
返回的新 Promise 会以相同状态和值(或原因)完成,并将其结果放入微任务队列,等待当前宏任务执行完毕后,在微任务阶段执行。
性能优化及避免内存泄漏和性能瓶颈
- 限制并发数量:
- 在处理大量 Promise 时,同时执行过多的 Promise 可能会导致内存和性能问题。可以通过限制并发数量来优化。
- 以下是使用
async/await
和队列来实现限制并发的示例:
function asyncTask() {
return new Promise((resolve) => {
setTimeout(() => {
resolve();
}, 1000);
});
}
async function runTasks(tasks, concurrency) {
const results = [];
const taskQueue = [...tasks];
const runningTasks = [];
while (taskQueue.length > 0 || runningTasks.length > 0) {
while (runningTasks.length < concurrency && taskQueue.length > 0) {
const task = taskQueue.shift();
const result = task();
results.push(result);
runningTasks.push(result);
}
await Promise.race(runningTasks);
runningTasks.splice(runningTasks.indexOf(await Promise.race(runningTasks)), 1);
}
return Promise.all(results);
}
// 示例使用
const tasks = Array.from({ length: 10 }, () => asyncTask);
runTasks(tasks, 3).then(() => {
console.log('All tasks completed');
});
- 在上述代码中,
runTasks
函数接受任务数组和并发数量作为参数。它使用一个队列来管理任务,每次只允许 concurrency
数量的任务同时执行。当有任务完成时,从队列中取出新任务继续执行,直到所有任务完成。这样可以有效避免同时执行过多任务导致的性能问题。
- 及时释放资源:
- 在 Promise 处理过程中,确保及时释放不再使用的资源。例如,如果 Promise 中创建了定时器、网络连接等资源,在 Promise 完成后要及时清理这些资源。
- 以下是一个简单的示例,展示如何在 Promise 完成后清除定时器:
function timerPromise() {
return new Promise((resolve) => {
const timer = setTimeout(() => {
clearTimeout(timer);
resolve();
}, 1000);
});
}
- 在这个示例中,当定时器触发时,先清除定时器,然后再
resolve
Promise,避免了定时器持续占用资源导致的潜在内存泄漏。