面试题答案
一键面试数组方法并发执行的底层机制
Promise.all
结合数组迭代方法实现并发- 在 JavaScript 中,
Promise.all
接受一个 Promise 数组作为参数。当使用数组迭代方法(如map
)结合Promise.all
实现并发时,map
会遍历数组的每个元素,并为每个元素创建一个 Promise。 Promise.all
会等待所有传入的 Promise 都 resolved 或者其中任何一个 rejected。如果所有 Promise 都 resolved,Promise.all
返回的 Promise 将以包含所有 resolved 值的数组形式 resolved;如果有任何一个 Promise rejected,Promise.all
返回的 Promise 会立即 rejected,且 reject 的原因就是第一个 rejected 的 Promise 的原因。
- 在 JavaScript 中,
- JavaScript 引擎对内存和线程的管理
- 内存管理:JavaScript 是垃圾回收机制管理内存。在并发执行时,每个 Promise 及其相关联的数据结构(如回调函数等)都会占用内存。当 Promise 被 resolved 或 rejected 后,其相关的一些不再被引用的内存空间会被垃圾回收器回收。但是,如果在并发过程中创建了大量的 Promise 且长时间不释放引用,就可能导致内存占用过高。
- 线程管理:JavaScript 是单线程语言,运行在主线程上。它通过事件循环(event loop)机制来处理异步操作。当遇到
Promise
等异步任务时,会将其回调函数放入任务队列(task queue)中。主线程执行完当前调用栈(call stack)中的所有同步代码后,会从任务队列中取出任务放入调用栈执行,这使得看起来像是并发执行,但实际上还是单线程顺序执行。
高并发场景下的优化
- 优化代码结构
- 分批处理:将数千个元素分成多个批次处理,而不是一次性全部并发处理。这样可以控制同时处于活跃状态的 Promise 数量,减少内存压力。
- 合理使用
async/await
:在处理异步操作时,使用async/await
让代码看起来更同步,易于理解和维护,同时可以更好地控制异步操作的顺序和并发数量。
- 调整并发数量
- 限制并发数:可以使用一个队列来控制并发数量。例如,维护一个最大并发数为
maxConcurrent
的队列,当队列中的任务数量达到maxConcurrent
时,等待有任务完成后再添加新任务。
- 限制并发数:可以使用一个队列来控制并发数量。例如,维护一个最大并发数为
示例代码
// 模拟一个异步任务
function asyncTask(data) {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`Processed data: ${data}`);
resolve(data);
}, 100);
});
}
// 优化前,一次性并发处理所有任务
function processAllAtOnce(dataArray) {
return Promise.all(dataArray.map(asyncTask));
}
// 优化后,分批处理任务
async function processInBatches(dataArray, batchSize) {
const results = [];
for (let i = 0; i < dataArray.length; i += batchSize) {
const batch = dataArray.slice(i, i + batchSize);
const batchResults = await Promise.all(batch.map(asyncTask));
results.push(...batchResults);
}
return results;
}
// 模拟数据数组
const largeDataArray = Array.from({ length: 1000 }, (_, i) => i + 1);
// 调用优化后的方法
processInBatches(largeDataArray, 100).then((finalResults) => {
console.log('Final results:', finalResults);
});
在上述代码中,processAllAtOnce
方法会一次性并发处理所有任务,可能在高并发场景下导致内存和性能问题。而 processInBatches
方法将数据分成每批 batchSize
个任务进行处理,有效控制了并发数量,减少内存压力和性能瓶颈。