问题描述
- 先说一下项目的需求:使用Chrome插件对bug提交系统的数据信息进行统计,bug提交系统大概长这个样子:

- 由于这个页面中只是包含部分信息,详细信息仍需要点击链接进入查看详情。详情类似于这样:

- 采用Chrome插件循环获取每一条数据信息的详细内容,对获取的内容进行单独存储,以方便后续插件添加按条件筛选功能
问题分析
- Chrome插件开发过程中,需求是对某一数据系统的每一条内容进行获取与统计,这就涉及到一个问题——需要循环获取列表中每一条数据的详情链接,并且加载链接中的HTML文件以进行DOM操作
- 显然在网页中创建一个1px-1px的iframe用来循环加载各个网页的url在数据量较小的情况下是可行的,但是当数据量以千、甚至以万为单位时,上述方法显然不会有很好的效率可言
- 为此,考虑到采集数据时均为对DOM的操作,如果仅仅请求每条数据链接的HTML文件并转换为DOM文件进行操作 来取代 采用浏览器创建iframe渲染HTML再加载DOM的方式 是否能够缩短处理每一条数据的时间,为此,作者进行了一次尝试。开发框架和流程如下:
- 采用popup作为控制窗口,向background和content发送动作信号
- background作为数据存放仓库,以json的形式存放获取的数据
- content嵌入目标网页中,用于获取网页中的数据信息
- 运行流程为:
- 1.popup发送数据采集信号->content获得信号并开始采集数据信息->content采集的数据信息发送给background中进行存储
- 2.popup发送数据获取信号->background获得信号并将对应数据返回给popup
涉及技术
- 使用js操作网页的cookies以达到更改网页中某些布局显示的功能:
// 创建一个时间对象
var d = new Date();
// 设置一个1天的有效期,防止浏览器会自动清除超时的cookie的值
d.setTime(d.getTime() + (24*60*60*1000));
// 添加参数
var expires = "expires="+d.toUTCString();
// 将关键参数注入到网页的cookies中
document.cookie = 'pagerBugBrowse' + "=" + request.pagerBugBrowse + "; " + expires;
// 刷新网页,使刚刚的更改生效
window.location.reload(true)
- 通过修改cookies来让网页能够以一个页面加载超多条数据的方式进行显示,方便后续数据获取的操作
- 利用XMLHttpRequest实现依靠url链接仅仅获得网址中的HTML信息:
function makeHttpObject() {
return new XMLHttpRequest();
}
var request = makeHttpObject();
request.open("GET", "http://www.baidu.com", true);
request.send(null);
request.onreadystatechange = function() {
console.log(request.responseText)
};
- 创建一个新的Element,将步骤2中获得的HTML字符串添入
var wrapper = document.createElement('html')
wrapper.innerHTML = request.responseText
此时便可以通过常规的js获取DOM元素的方法获得目标元素了
同步和异步耗时测试
- 在循环中使用XMLHttpRequest()创建ajax来对网址中的html文件的dom元素进行获取,由于XMLHttpRequest()的‘get’请求是一个耗时操作,常会出现对当前网址的dom操作尚未结束就加载了下一个网址,产生的直接结果就是“仅有最后一个网址得到了实现”。过程中的请求全都被跳过了
- 为此,大佬提供了解决方案——详解JavaScript for循环中发送AJAX请求问题
精简为如下两种:
同步方法
var path = document.getElementById("path").value;
var xmlHttp = new XMLHttpRequest()
for (var i = 0; i < urlList.length; i++) {
xmlHttp.onreadystatechange = function() {
if(xmlHttp.readyState == 4){
// 执行你的代码
}
}
xmlHttp.open("GET", urlList[i], false);
xmlHttp.send(null);
}
- 同步方法虽然能够实现循环加载数据的操作,但是非常耗时且会对程序造成阻塞,因此不推荐
异步方法
function disButton(name, actionName, resquestParmName) {
var xmlHttp;
for (var i = 0; i < urlList.length; i++) {
xmlHttp = new XMLHttpRequest();
xmlGetData(xmlHttp,urlList[i]);
}
}
function xmlGetData(xmlHttp,url){
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
// 你的代码
}
}
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
- 注意 ,一定要将执行代码单独封装为一个独立的函数,让程序执行时不断的创建新的XMLHttpRequest()对象以防止执行覆盖的问题出现
运行速度结果
- 为了直观看出执行速度的差异,选用包含100个子链接的网页进行测试,测试结果如下:
- 采用同步执行方法共耗时8501ms
- 采用异步执行方法共耗时3282ms
- (以上数据均在连续10次测试中取时间最长的一次结果进行记录)执行结果附在下方:
- 同步执行:
main.js:96 1661246119250
main.js:96 1661246119406
...
main.js:96 1661246127669
main.js:96 1661246127751
- 异步执行:
main.js:44 1661246537493
main.js:44 1661246537613
...
main.js:44 1661246540711
main.js:44 1661246540775
6350

被折叠的 条评论
为什么被折叠?



