JS如何实现遍历进度显示并且不增加浏览器IDLE时间?

JS如何实现遍历进度显示并且不增加浏览器IDLE时间?

在做一个纯前端的日志文件分析工具。这个过程中需要进行两次遍历。

最初没考虑性能问题,直接用的 for ,5w行的样本数据大概要35秒才能完成,这效率相当堪忧……(虽然后来发现是开着 Chrome 调试工具 Performance 时性能巨烂,不开的话大概是9秒)
一般数据都是 30w行 起步的(现在直接载入30w行的日志 Chrome 直接就死了)。

考虑至少加一个实时进度,但是用 for 遍历没法实时渲染。看网上有做法是改写成 setTimeout 的方式做自身回调,大概就是这种感觉:

之前:

let result = [];
for (let i = 0; i < data.length; i++) {
    //干事出结果
    //result.push(结果)
}

之后:

let i = 0;
let result = []
let doThing = function(i, data, result) {
    //渲染进度条(还没写)
    //干事出结果
    //result.push(结果)
    i++;
    if (i < data.length) {
        setTimeout(function() {
            generateRawData(i, data, result);
        }, 0);
    } else {
        //下一步
    }
};
generateRawData(0, data, result);

功能倒是实现了,但是发现速度变得特别慢(我还没有写渲染进度的代码所以肯定不是前端渲染慢的问题)开了 Chrome 调试工具 Performance ,发现大部分时间都是 IDLE ,也就是说浏览器闲着没干事,这不行啊。

图1,使用 for 遍历时的 Performance 图:
图片描述

图2,使用 setTimeout 遍历时的 Performance 图:
图片描述

JS如何实现遍历进度显示并且不增加浏览器IDLE时间不?感觉 setTimeout 这种渲染办法貌似是传统方法,现在有没有什么新 API 能实现类似的事情?

阅读 4.1k
4 个回答

setTimeout 有个最小时间间隔的 http://rogerfederer.iteye.com...
你跑一条数据的时间远远小于这个间隔,就导致了浏览器大部分时间在 IDLE

所以,你一次多跑个 几百/上千 条再 setTimeout
或者 检测一次运行时间超过 setTimeout最小时间间隔(比如 10-15 ms)
再进行 setTimeout 跑下一循环

webworker 应该时更好的选择

为什么用settimeout啊? 感觉这种需求不适合用settimeout或者setinterval

你可以使用RAF或者RID,或者直接用webworker多好啊。

你一组一组(1000条?)渲染,当中用settimeout,停顿个100ms,让cpu和内存喘口气。

webworker requestidlecallback?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题