• 防止浏览器假死的方法 - HTML 5 Web开发
    时间:2012-02-03   作者:佚名   出处:互联网

    在Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出“脚本运行时间过长“的提示框,如果出现这种情况说明你的脚本已经失控了。针对这种情况如何控制?请看下文。

    一个浏览器至少存在三个线程: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亿的时候,普通做法耗时已经很长,且一般会卡死了。

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

    普通方法在Chrome15下的效果

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

    网友留言/评论

    我要留言/评论

    相关文章

    网站首页12大元素:网站首页需要身兼数职,提供给来自不同地方的观众们使用。它不像一个专用的登陆页面——来自不同通道的流量会显示各自特定的信息,并执行相对应的指令。登陆页面有更高的转换率,因为它是有针对性的,是对来访者最重要的一部分。
    照片共享 Flickr 网站架构分析:Flickr.com 是网上最受欢迎的照片共享网站之一,还记得那位给Windows Vista拍摄壁纸的Hamad Darwish吗?他就是将照片上传到Flickr,后而被微软看中成为Vista壁纸御用摄影师。
    视频网站优酷网架构学习笔记:前面给大家介绍过视频网站龙头老大YouTube的技术架构,相信大家看了都会有不少的感触,互联网就是这么一个神奇的东西。今天我突然想到,优酷网在国内也算是视频网站的老大了,不知道他的架构相对于YouTube是怎么样的,于是带着这个好奇心去网上找了优酷网架构的各方面资料,虽然谈得没有YouTube那么详细,但多少还是挖掘了一点,现在总结一下,希望对喜欢架构的朋友有所帮助。
    大型视频网站YouTube架构学习笔记:这几天一直在关注和学习一些大型网站的架构,希望有一天自己也能设计一个高并发、高容错的系统并能应用在实践上。今天在网上找架构相关的资料时,看到一个被和谐的视频网站YouTube的架构分析,看了以后觉得自己又向架构走近了一步,于是赶快拿出来与大家一起分享。
    Twitter网站架构介绍:作为140个字的缔造者,twitter太简单了,又太复杂了,简单是因为仅仅用140个字居然使有几次世界性事件的传播速度超过任何媒体,复杂是因为要为2亿用户提供这看似简单的140个字的服务,这真的是因为简单,所以复杂。可是比较遗憾的是目前在中国大陆twitter是无法访问的,但作为一个爱好架构的程序猿,这道墙是必须得翻的,墙外的世界更精彩。今天就结合网络上的一些资料,来浅谈一下我对twitter网站架构的学习体会,希望给路过的朋友一点启示.......
    新年伊始,给设计师的 10 条建议:去年我们做的确实很不错。我们为自己而站了起来。我们不再免费工作,我们也开始有了自己的小金库。我们又一次发现了新的排版,我们学会了在设计前先考虑手机客户端的问题。
    我们学会了制作能响应的交互性网站,我们不再在设计上与Lorem ipsum较劲,而开始关注我们正在设计的、实实在在的东西。
    今年呢?今年是一个要命的黄金年代!去年我们是处于训练期,今年我们要开始战斗了!
    推荐12个漂亮的CSS3按钮实现方案:在过去,我们都是使用图片或者JavaScript来实现漂亮的按钮效果,随着越来越多的浏览器对CSS3的支持和完善,使用CSS3来实现美观的按钮已没有太多的障碍。今天,本文收集了12个很不错的CSS3按钮方案并有相关的使用教程。
    HTC刷机和获取ROOT权限详细图文教程:昨晚刷机,花了近4个小时,终于把HTC g12给搞定了,并且还获取了root权限。其中看了大量的资料,为了避免网友们重复造轮子,特此记录一下刷机过程。在此,感谢安智网和安极网论坛,这对我刷机有很大的帮助,其中本文引用了他们的一些资料。废话不多说,开始。
    20 个很有用的 CSS 图形和图表技术及教程:图形和图表主要用于以如饼图、折线图、条形图等方式展示数值数据的直观形式。有众多的技术利用CSS3来创建不同的图表。在任何Web行业,一个良好和优秀的数据演示可以让客户直观了解你分析的内容。
    25 个富有灵感的企业网站设计实例:在当今的企业世界中,拥有一个能够吸引用户的网站,将会是一个很大的优势,因此很多公司企业越来越注重网站的设计,本文将介绍国际上一些比较新颖而富有灵感的企业网站实例,给设计师们提供一些思路。