请选择 进入手机版 | 继续访问电脑版

662p开源IT论坛

 找回密码
 立即注册
查看: 16549|回复: 13

怎样防止浏览器假死在html5中

[复制链接]

682

主题

6

听众

6009

积分

管理员

Rank: 9Rank: 9Rank: 9

活跃会员 热心会员 推广达人 突出贡献 荣誉管理 社区QQ达人

发表于 2013-2-23 10:48:10 |显示全部楼层

一个浏览器至少存在三个线程:js引擎线程(处理js)、GUI渲染线程(渲染页面)、浏览器事件触发线程(控制交互)。

JavaScript引擎是基于事件驱动单线程执行的,JS引擎一直等待着任务队列中任务的到来然后加以处理,浏览器无论再什么时候都只有一个JS线程在运行JS程序。

GUI 渲染线程负责渲染浏览器界面,当界面需要重绘(Repaint)或由于某种操作引发回流(reflow)时,该线程就会执行。但需要注意 GUI渲染线程与JS引擎是互斥的,当JS引擎执行时GUI线程会被挂起,GUI更新会被保存在一个队列中等到JS引擎空闲时立即被执行。

事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待JS引擎的处理。这些事件可来自JavaScript引擎当前执行的代码块如setTimeOut、也可来自浏览器内核的其他线程如鼠标点击、AJAX异步请求等,但由于JS的单线程关系所有这些事件都得排队等待JS引擎处理。

了解了浏览器的内核处理方式就不难理解浏览器为什么会进入假死状态了,当一段JS脚本长时间占用着处理机就会挂起浏览器的GUI更新,而后面的事件响应 也被排在队列中得不到处理,从而造成了浏览器被锁定进入假死状态。另外JS脚本中进行了DOM操作,一旦JS调用结束就会马上进行一次GUI渲染,然后才 开始执行下一个任务,所以JS中大量的DOM操作也会导致事件响应缓慢甚至真正卡死浏览器,如在IE6下一次插入大量的HTML。而如果真的弹出了“脚本 运行时间过长“的提示框则说明你的JS脚本肯定有死循环或者进行过深的递归操作了。

现在如果遇到了这种情况,我们可以做的不仅仅是优化 代码,html5的webWorkers提供了js的后台处理线程的API,它允许将复杂耗时的单纯js逻辑处理放在浏览器后台线程中进行处理,让js线 程不阻塞UI线程的渲染。这个线程不能和页面进行交互,如获取元素、alert等。多个线程间也是可以通过相同的方法进行数据传递。

直接看代码:

例子:用户输入一个数字,进行加法运算(+=)

以前的做法:

  • <!DOCTYPE HTML>
  • <html lang="en">
  • <head>
  •     <meta charset="UTF-8">
  •     <title>webworkers--calculate</title></head>
  • <body>
  •     <input id="num" name="num" type="text"/>
  •     <button onclick = "calculate()">计算</button><br />
  •     <div id="result" style="color:red;"></div>
  •     <div id="time" style="color:red;"></div>
  •     <script type="text/javascript" src="calculate.js"></script>
  •     <script type="text/javascript">        function calculate(){  
  •             data1 = new Date().getTime();  
  •             var num = document.getElementById("num").value;  
  •             var val = parseInt(num,10);  
  •             var result =0;  
  •             for(var i =0; i<num;i++){  
  •                 result += i;  
  •             }  
  •             data2 = new Date().getTime();  
  •             document.getElementById("result").innerHTML ="计算结果:"+result;  
  •             document.getElementById("time").innerHTML ="普通 耗时:"+ (data2 - data1)+"ms";  
  •         }  
  •     </script>
  • </body>
  • </html>

使用webWorkers以后:

calculate.html

  • <!DOCTYPE HTML>
  • <html lang="en"><head>
  •     <meta charset="UTF-8">
  •     <title>webworkers--calculate</title>
  • </head>
  • <body>
  •     <input id="num" name="num" type="text"/>
  •     <button onclick = "calculate()">计算</button><br />
  •     <div id="result" style="color:red;"></div>
  •     <div id="time" style="color:red;"></div>
  •     <script type="text/javascript" src="calculate.js"></script>
  •     <script type="text/javascript">
  •         var worker = new Worker("calculate.js");  
  •         var data1 =0;  
  •         var data2 =0;  
  •         worker.onmessage = function(event){  
  •                 var data = event.data;  
  •                 data2 = new Date().getTime();  
  •                 document.getElementById("result").innerHTML ="计算结果:"+data;  
  •                 document.getElementById("time").innerHTML ="workers 耗时:"+ (data2 - data1)+"ms";  
  •             };  
  •          function calculate(){  
  •             data1 = new Date().getTime();  
  •             var num = document.getElementById("num").value;   
  •            var val = parseInt(num,10);  
  •             worker.postMessage(val);  
  •         }  
  •     </script>
  • </body>
  • </html>

calculate.js

  • onmessage = function(event){  
  •     var num = event.data;  
  •     var result = 0;  
  •     for(var i = 0; i<num;i++){  
  •         result += i;  
  •     }  
  •     postMessage(result);  
  • };

webWorker需要将代码放入web服务器中, 如果使用的是localhost请用高版本的chrome浏览器打开,firefox浏览器在处理localhost的时候会出现“Could not get domain!”的错误,关于这个可以参考:https://bugzilla.mozilla.org/show_bug.cgi?id=682450 对比上面的两种实现方式,当计算值达到100亿的时候,普通做法耗时已经很长,且一般会卡死了。


webWorkers在Chrome15下的效果

更正:getTime()返回的应该是毫秒(ms),而不是秒(s)。

如下图所示:


普通方法在Chrome15下的效果

可见webWorkers在未来的web应用中还是非常有价值的。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

哎...今天够累的,签到来了1...

0

主题

1

听众

1万

积分

论坛元老

Rank: 8Rank: 8

社区QQ达人 活跃会员 热心会员 推广达人 宣传达人 突出贡献 优秀版主 荣誉管理

发表于 2013-7-11 16:13:43 |显示全部楼层
看帖要回,回帖才健康,在踩踩,楼主辛苦了!
回复

使用道具 举报

0

主题

0

听众

80

积分

注册会员

Rank: 2

社区QQ达人 最佳新人 活跃会员 热心会员 推广达人

发表于 2013-8-1 14:40:31 |显示全部楼层
回帖才健康、
千锋3G培训学院:
北京android培训
回复

使用道具 举报

0

主题

0

听众

16

积分

新手上路

Rank: 1

社区QQ达人 最佳新人

发表于 2013-9-9 15:29:48 |显示全部楼层
IOS最新资讯, http://ioskaifa.uplook.cn/
回复

使用道具 举报

0

主题

1

听众

1万

积分

论坛元老

Rank: 8Rank: 8

社区QQ达人 活跃会员 热心会员 推广达人 宣传达人 突出贡献 优秀版主 荣誉管理

发表于 2014-5-29 22:53:25 |显示全部楼层
看起来不错
回复

使用道具 举报

0

主题

0

听众

1万

积分

论坛元老

Rank: 8Rank: 8

社区QQ达人 活跃会员 热心会员 推广达人 宣传达人 突出贡献 优秀版主 荣誉管理

发表于 2014-8-13 02:56:02 |显示全部楼层
专业抢沙发的!哈哈
回复

使用道具 举报

0

主题

0

听众

1万

积分

论坛元老

Rank: 8Rank: 8

社区QQ达人 活跃会员 热心会员 推广达人 宣传达人 突出贡献 优秀版主 荣誉管理

发表于 2014-9-28 18:51:46 |显示全部楼层
支持楼主,用户楼主,楼主英明呀!!!
回复

使用道具 举报

0

主题

1

听众

1万

积分

论坛元老

Rank: 8Rank: 8

社区QQ达人 活跃会员 热心会员 推广达人 宣传达人 突出贡献 优秀版主 荣誉管理

发表于 2014-12-5 04:55:24 |显示全部楼层
我也顶起出售广告位
回复

使用道具 举报

0

主题

1

听众

1万

积分

论坛元老

Rank: 8Rank: 8

社区QQ达人 活跃会员 热心会员 推广达人 宣传达人 突出贡献 优秀版主 荣誉管理

发表于 2015-1-30 07:51:00 |显示全部楼层
回复一下先
回复

使用道具 举报

0

主题

2

听众

1万

积分

论坛元老

Rank: 8Rank: 8

社区QQ达人 活跃会员 热心会员 推广达人 宣传达人 突出贡献 优秀版主 荣誉管理

发表于 2015-2-23 08:29:37 |显示全部楼层
我擦!我要沙发!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

我的微博|我的微博|我的微博|手机版|Archiver|662p开源网 ( 粤ICP备12089784号 )

GMT+8, 2019-12-15 08:50 , Processed in 0.375000 second(s), 32 queries .

Powered by Discuz! X2.5

© 2001-2013 662p Inc.

回顶部