使用 requestidlecallback 或 settimeout 将数组遍历拆分为多个时间片执行,以避免阻塞主线程。核心做法是维护一个索引指针,每次任务只处理一小部分数据,处理完后通过回调继续下一批,直到索引超过数组长度。若数组为空或长度为0,则直接跳过不执行。

如何基于 requestIdleCallback 实现非阻塞遍历
利用 requestIdleCallback 可以在浏览器空闲时执行代码,适合对实时性要求不高但需要保持页面响应的场景。该 API 会传入一个包含 didTimeout 和 timeRemaining 的接口对象,开发者需根据剩余时间决定处理多少元素。具体实现时,定义一个全局或闭包变量记录当前处理的索引,每次调用时检查剩余时间是否足够处理下一个元素,若不足则保存状态并退出,等待下一次回调。

const data = Array.from({length: 1000}, (_, i) => i);
let index = 0;
function processBatch(deadline) {
while (index < data.length && deadline.timeRemaining() > 0) {
console.log('Processing:', data[index]);
index++;
}
if (index < data.length) {
requestIdleCallback(processBatch);
} else {
console.log('Done');
}
}
requestIdleCallback(processBatch);预期结果:控制台分批打印数字 0 到 999,中间穿插其他 UI 渲染操作,最终输出 'Done'。
立即学习“Java免费学习笔记(深入)”;
如何使用 setTimeout 进行简单分片处理
当不支持 requestIdleCallback 或需要更简单的控制逻辑时,可以使用 setTimeout 将任务推入宏任务队列。这种方式虽然不能精确利用空闲时间,但能有效防止长时间同步执行导致的卡顿。实现上同样需要维护索引,每次处理固定数量的元素后,设置新的定时器继续处理剩余部分。这种方法的优势在于兼容性更好,且可以通过调整超时时间来平衡响应速度和吞吐量。

const data = Array.from({length: 1000}, (_, i) => i);
let index = 0;
const chunkSize = 100;
function processChunk() {
const end = Math.min(index + chunkSize, data.length);
for (let i = index; i < end; i++) {
console.log('Processing:', data[i]);
}
index = end;
if (index < data.length) {
setTimeout(processChunk, 0);
} else {
console.log('Done');
}
}
processChunk();预期结果:每批次处理 100 个元素,共 10 批次,最终输出 'Done'。
当数组长度为 0 时程序行为是什么
在两种实现中,当输入数组长度为 0 时,程序均不会进入循环或递归调用,而是直接完成并输出结束标志。对于 requestIdleCallback 方案,初始调用时 index 为 0,data.length 也为 0,条件 index 不成立,直接执行 <code>console.log('Done')。对于 setTimeout 方案,初始调用时 end 计算结果为 0,循环不执行,index 更新为 0,条件 index 同样不成立,直接输出 'Done'。这种设计确保了空输入下的安全性与一致性。


















