js什么是分时函数?如何封装分时函数?
前言
最近做项目时遇到一个渲染问题,经过查找多处资料后看到一个新名词分时函数 ,接下来就总结一篇我看到的、学到的东西。
开始
什么是分时函数呢?我觉得大家在项目中也会遇到这种情况:就是有时候是我们主动需要大量的频繁调用某个函数,比如你需要向页面插入1000个元素乃至更多元素,在短时间内往页面中大量添加 DOM节点显然会让浏览器吃不消,我们看到的结果往往就是浏览器的卡顿甚至假死。
但是如果把这个1000个元素分批绘制, 那这个时候浏览器的压力就小了。 这个就是分时,那分时函数当然就是咱们把逻辑封装成函数了。
代码示例
我们来举一个简单的例子:
const btn = document.querySelector('.btn');
const datas = new Array(1000000).fill(0).map((_, i) => i); // 生成1000000个数组元素
// 点击代码后循环数组,向页面插入div元素
btn.onclick = () => {
for(const i of datas){
const el = document.createElement('div');
el.innerText = i;
document.body.appendChild(el);
}
}
页面中有个按钮,点击后向页面中插入1000000个div元素,代码很简单。你会发现点击按钮后页面卡住了,等了很长时间页面才有反应。
这里我们简单说一下造成卡顿的原因:
如上图,我们知道浏览器是每16.6ms渲染一次,但是现在呢,有一个任务需要的时间比较长,没有给浏览器留下任何的空间进行渲染,所以就导致页面的卡顿。
所以我们最好把这个任务进行分片,不要一次性去执行,等一下浏览器渲染,执行完一片后再去执行下一分片,这样就不会造成卡顿了。
代码封装
const btn = document.querySelector('.btn');
const datas = new Array(1000000).fill(0).map((_, i) => i); // 生成1000000个数组元素
// 点击代码后循环数组,向页面插入div元素
btn.onclick = () => {
const taskHandler = (i) => {
const el = document.createElement('div');
el.innerText = i;
document.body.appendChild(el);
}
browserScheduler(datas, taskHandler);
}
// 分片执行
function performChunk(data, taskHandler, scheduler) {
// 允许直接传执行次数
if (typeof data === 'number') {
data = {
length: data
}
}
if (data.length === 0) {
return;
}
let i = 0;
// 开启下一分片的执行
function _run() {
if (i >= data.length) {
return;
}
scheduler((signal) => {
while (signal() && i < data.length) {
taskHandler(data[i], i);
i++;
}
});
// 一个渲染帧中,空闲时分片执行
requestIdleCallback((idle) => {
while (idle.timeRemaining() > 0 && i < data.length) {
taskHandler(data[i], i);
i++;
}
// 此次分片执行完成,执行下一分片
_run();
})
}
_run();
}
// 浏览器环境,使用requestIdleCallback
function browserScheduler(data, taskHandler) {
const scheduler = (task) => {
return requestIdleCallback((idle) => {
task(() => idle.timeRemaining() > 0);
});
}
performChunk(data, taskHandler, scheduler)
}
// node环境,使用setImmediate
function nodeScheduler(data, taskHandler) {
const scheduler = (task) => {
return setImmediate(() => {
task(() => true);
});
}
performChunk(data, taskHandler, scheduler)
}
// 其他环境 ...
这里列举了 requestIdleCallback 和 setImmediate ,也可以其他方式如 setTimeout 等方式,根据需求修改 scheduler。
结语
分时函数作为一种有效的性能优化手段,其核心在于通过控制函数执行的节奏,减轻瞬时压力,确保用户界面的流畅性与系统的响应速度。
掌握并合理运用分时函数策略,对于提升Web应用的用户体验至关重要。在未来面对高性能需求及优化挑战时,希望本文介绍的方法能成为你开发工具箱中的又一利器。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 从前从前 Bolg