有一位同事跟大家说他在网上看到一道面试题:“如果后台传给前端几万条数据,前端怎么渲染到页面上?”,如何回答? 于是办公室沸腾了, 同事们讨论开了, 你一言我一语说出自己的方案。 有的说直接循环遍历生成html插到页面上;有的说应该用分页来处理;还有的说这个面试官是个白痴, 哪有后台传几万条数据给前端这种情况的;我仔细思考了一下,先不论后端到底会不会白痴到传几万条数据给前端,假如真碰到这种情况,那么如果前端获取到数据以后, 直接将数据转换成html字符串,通过DOM操作插入到页面,势必导致页面运行出现卡顿, 为此我还特意写了一个 demo测试了一下, 代码如下

$.get("data.json", function (response) {
//response里大概有13万条数据
loadAll( response );
}); function loadAll(response) {
var html = "";
for (var i = 0; i < response.length; i++) {
var item = response[i];
html += "<li>title:" + item.title + " content:" + item.content + "</li>";
}
$("#content").html(html);
}

data.json中大概有13万条数据左右, 通过ajax获取数据后以最简单粗暴的方法展示数据,在chrome浏览器下, 刷新页面到数据显示,我心中默数, 整个过程大概花掉5秒钟左右的时间, 卡顿非常明显。 我大致观察了一下代码的运行时间,发现循环生成字符串这过程其实并不算太耗时, 性能瓶颈是在将html字符串插入到文档中这个过程上, 也就是 $("#content").html(html); 这句代码的执行, 毕竟有13万个li元素要被挺入到文档里面, 页面渲染速度缓慢也在情理之中。

既然一次渲染13万条数据会造成页面加载速度缓慢,那么我们可以不要一次性渲染这么多数据,而是分批次渲染, 比如一次10000条,分13次来完成, 这样或许会对页面的渲染速度有提升。 然而,如果这13次操作在同一个代码执行流程中运行,那似乎不但无法解决糟糕的页面卡顿问题,反而会将代码复杂化。 类似的问题在其它语言最佳的解决方案是使用多线程,JavaScript虽然没有多线程,但是setTimeout和setInterval两个函数却能起到和多线程差不多的效果。 因此,要解决这个问题, 其中的setTimeout便可以大显身手。 setTimeout函数的功能可以看作是在指定时间之后启动一个新的线程来完成任务。

$.get("data.json", function (response) {
//response里大概有13万条数据
loadAll( response );
}); function loadAll(response) {
//将13万条数据分组, 每组500条,一共260组
var groups = group(response);
for (var i = 0; i < groups.length; i++) {
//闭包, 保持i值的正确性
window.setTimeout(function () {
var group = groups[i];
var index = i + 1;
return function () {
//分批渲染
loadPart( group, index );
}
}(), 1);
}
} //数据分组函数(每组500条)
function group(data) {
var result = [];
var groupItem;
for (var i = 0; i < data.length; i++) {
if (i % 500 == 0) {
groupItem != null && result.push(groupItem);
groupItem = [];
}
groupItem.push(data[i]);
}
result.push(groupItem);
return result;
} var currIndex = 0; //加载某一批数据的函数
function loadPart( group, index ) {
var html = "";
for (var i = 0; i < group.length; i++) {
var item = group[i];
html += "<li>title:" + item.title + index + " content:" + item.content + index + "</li>";
}
//保证顺序不错乱
while (index - currIndex == 1) {
$("#content").append(html);
currIndex = index;
}
}

以上代码大致的执行流程是

1. 用ajax获取到需要处理的数据, 共13万条
2. 将数组分组,每组500条,一共260组
3. 循环这260组数据,分别处理每一组数据, 利用setTimeout函数开启一个新的执行线程(异步),防止主线程因渲染大量数据导致阻塞。

loadPart函数中有这段代码

while (index - currIndex == 1) {
$("#content").append(html);
currIndex = index;
}

是为了保证不同的线程中最终插入html到文档中时顺序的一致性, 不至于同时执行的代码在插入html时互相篡位。

通过这种方式执行, 页面瞬间就刷出来了,不用丝毫等待时间。 从同步改为异步,虽然代码的整体资源消耗增加了, 但是页面却能瞬间响应, 而且, 前端的运行环境是用户的电脑,因此些许的性能损失带来的用户体验提升相对来说还是值得的。

虽然示例中提到的情况在现实环境中几乎不可能出现, 但是在我们平时的工作中总会有一些似是而非的场景出现, 利用里面的处理思路, 或许对我们解决问题会有一定的帮助。

ps:setTimeout并不算真正的多线程, 但是为了方便表达,便借用了线程一词

JavaScript如何一次性展示几万条数据的更多相关文章

  1. 主要看思路:区域数据去重 + JavaScript一次性展示几万条数据实例代码

    近期做1功能,Gis地图 基于百度地图api , 会遇到的问题的, 如后台接口给的数据很多,大几千上万的,如果拿了数据直接渲染dom ,这滋味爽爽的. 再遇上 客户端浏览器悲催的,这卡顿就来了... ...

  2. 最短时间(几秒内)利用C#往SQLserver数据库一次性插入10万条数据

    用途说明: 公司要求做一个数据导入程序,要求将Excel数据,大批量的导入到数据库中,尽量少的访问数据库,高性能的对数据库进行存储.于是在网上进行查找,发现了一个比较好的解决方案,就是采用SqlBul ...

  3. QTreeView处理大量数据(使用1000万条数据,每次都只是部分刷新)

    如何使QTreeView快速显示1000万条数据,并且内存占用量少呢?这个问题困扰我很久,在网上找了好多相关资料,都没有找到合理的解决方案,今天在这里把我的解决方案提供给朋友们,供大家相互学习. 我开 ...

  4. 极限挑战—C#+ODP 100万条数据导入Oracle数据库仅用不到1秒

    链接地址:http://www.cnblogs.com/armyfai/p/4646213.html 要:在这里我们将看到的是C#中利用ODP实现在Oracle数据库中瞬间导入百万级数据,这对快速批量 ...

  5. Qt中提高sqlite的读写速度(使用事务一次性写入100万条数据)

    SQLite数据库本质上来讲就是一个磁盘上的文件,所以一切的数据库操作其实都会转化为对文件的操作,而频繁的文件操作将会是一个很好时的过程,会极大地影响数据库存取的速度.例如:向数据库中插入100万条数 ...

  6. Mvc+Dapper+存储过程分页10万条数据

    10万条数据采用存储过程分页实现(Mvc+Dapper+存储过程) 有时候大数据量进行查询操作的时候,查询速度很大强度上可以影响用户体验,因此自己简单写了一个demo,简单总结记录一下: 技术:Mvc ...

  7. EDG夺冠!用Python分析22.3万条数据:粉丝都疯了!

    一.EDG夺冠信息 11月6日,在英雄联盟总决赛中,EDG战队以3:2战胜韩国队,获得2021年英雄联盟全球总决赛冠军,这个比赛在全网各大平台也是备受瞩目: 1.微博热搜第一名,截止2021-11-1 ...

  8. 绝对干货,教你4分钟插入1000万条数据到mysql数据库表,快快进来

    我用到的数据库为,mysql数据库5.7版本的 1.首先自己准备好数据库表 其实我在插入1000万条数据的时候遇到了一些问题,现在先来解决他们,一开始我插入100万条数据时候报错,控制台的信息如下: ...

  9. 1000万条数据导入mysql

    今天需要将一个含有1000万条数据的文本内容插入到数据库表中,最初自然想到的是使用Insertinto '表名'values(),(),()...这种插入方式,但是发现这种方式对1000万条数据量的情 ...

随机推荐

  1. linux虚拟机CentOS 7完整安装流程截图

    安装VMware虚拟机过程此处省略,只介绍在虚拟机上安装linux系统CentOS 7过程截图. 1 新建虚拟机 2 命名虚拟机,选择linux安装位置 3 选择虚拟机处理器数量和处理器核心数 4 分 ...

  2. Jenkins学习——Jenkins是什么

    Jenkins是什么 对于Jenkins是什么,百度百科给的答案是这样的:Jenkins是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 通过这句话,我们可以得到这样的一 ...

  3. matlab和C语言的break及continue测试

    break和continue语句 有两个附加语句可以控制while和for循环:break和continue语句.break语句可以中止循环的执行和跳到end后面的第一句执行,而continue只中止 ...

  4. (转)JAVA的整型与字符串相互转换

    JAVA的整型与字符串相互转换1如何将字串 String 转换成整数 int? A. 有两个方法: 1). int i = Integer.parseInt([String]); 或         ...

  5. 【闲聊PHP】编程界的萝莉小美女--PHP

    本文地址 01 前言--上了贼船 不知道何时就上了PHP的贼船了,开始了web的开发,记得差不多两年前我还是做传统电子行业的人,就是嵌入式的方向,那时在天津或摆弄手机,或下煤窑摆弄电话,抑或就是在医疗 ...

  6. C++待解

    //[要求]按以下描述和要求建立一个含有对象成员的类TeleBook,用类Record定义的数组是TeleBook的数据成员. // 写出所有定义成员函数的代码.执行主函数对其测试. Record私有 ...

  7. 安居客Android项目架构演进

    入职安居客三年从工程师到Team Leader,见证了Android团队一路走来的发展历程.因此有心将这些记录下来与大家分享,也算是对自己三年来一部分工作的总结.希望对大家有所帮助,更希望能得到大家宝 ...

  8. C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(上)

    译文,个人原创,转载请注明出处(C# 6 与 .NET Core 1.0 高级编程 - 41 ASP.NET MVC(上)),不对的地方欢迎指出与交流. 章节出自<Professional C# ...

  9. Angular.js之Router学习笔记

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  10. MAC本如何优雅的创建定时任务

    在MACOS上设置定时任务大体有两种方案.一种是使用crontab,一种是使用Schedule,今天结合我的使用简单介绍一下. 先说一下背景,为什么MAC可以用crontab.如果使用过Linux的同 ...