大量数据我是这样渲染的
时间:2023-03-30 18:13:29
CSS
简介事情的由来如下。目前负责公司核心业务Gis天眼系统的开发。遇到一个问题:后端返回上千条数据,导致浏览器渲染失败,浏览器几乎卡顿。后来想不出合适的解决方案,临时渲染了少量数据来解决。我记得很清楚,我曾经看过如何解决此类问题,但很遗憾我没有使用它,因为我没有思考就学习了,没有使用它就看到了。后来因为家里有事,请了假回家休息了一段时间。回来后开会,说同事意识到了上面的一个问题,用了js线程。然后我开始反复思考这个问题。有这篇文章。JS线程浏览器分为js线程、GUI渲染线程、事件触发线程等。大家都知道JS是单线程的,但是问题来了,单线程是如何实现异步的,比如我们经常使用的Ajax是如何实现的?当你真正理解了JS的EventLoop,你就明白了!哦,我明白了。这里我就线程展开讨论。想深入了解可以看这篇文章:10分钟看懂JS引擎的执行机制如何渲染大数据渲染大量数据肯定会涉及到GUI渲染线程和js线程。简单代码如下:
//js代码varapp=document.getElementById("app");varFragment=document.createDocumentFragment();for(vari=0;i<100;i++){varspan=document.createElement("span");span.innerHTML=i;app.appendChild(span);}//开发项目的时候,绝对不是这样的Dom。这里只是举个例子,从上面的代码可以分析出来,每个for循环都是用dom来渲染的。浏览器如何渲染它?JS线程是单线程的。如果它执行JS线程,GUI渲染线程肯定会等待。这样渲染大量数据会导致页面卡顿,甚至卡顿、崩溃。页面显示效果就是这些dom节点全部渲染一次。知道了这一点,我们就可以弄清楚如何解决它(渲染大量数据)。初步看代码执行方式如下:console.log(1);setTimeout(function(){console.log(2);},100);console.log(3);大家会说这很简单,输出132。我想说的是,你看过JS的EventLoop吗?看完你肯定知道原理了。首先判断JS是同步还是异步。同步会进入主进程,异步会进入事件表。异步任务在事件表中注册函数。当满足触发条件时,会被推入事件队列。进入主线程后,同步任务会继续执行,直到主线程空闲时,会去事件队列中检查是否有可执行的异步任务,如果有则推入主进程。在第一个版本中,我使用递归调用实现了如下代码:varapp=document.getElementById("app");varj=1;/***渲染方式**@number{number}数量**/functionshowDom(number){console.log('rendering'+(j++)+"times");for(vari=0;i
500){setTimeout(function(){showDom(500);init(count-500);},200);}else{showDom(计数);}}初始化(4000);可以看出,使用上述方法可以简单轻松地渲染大量数据。给用户的感觉就是当前数据很多,需要我一步步去渲染。比一次渲染上千条数据导致GUI渲染引擎卡顿甚至停滞要好得多。在第二个版本中,我参考本书使用了以下代码。/***分时函数??@ary{Arry}数据*@callback{Function}回调函数,一个参数,当前数据项*@count{Number}个数***/functiontimeChunk(ary,callback,count){varobjTs=Object.prototype.toString,//检测类型t;//timerif(objTs.call(ary)!==[objectArray]"){returnconsole.warn(ary+"---》它应该是Arry类型的");}if(objTs.call(callback)!==[objectFunction]"){returnconsole.warn(callback+"---"shouldbeacallbackfunction");}if(objTs.call(count)!=="[objectNumber]"){returnconsole.warn(count+"---"shouldbeoftypeNumber");}//开始执行函数functionstart(){for(vari=0;i