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

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

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

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

3:事件触发线程,当一个事件被触发时该线程会把事件添加到待处理队列的队尾,等待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应用中还是非常有价值的。

html5 WebWorkers 防止浏览器假死的更多相关文章

  1. setTimeout 导致的浏览器假死

    问题   前几天,同事遇到一个浏览器假死的问题.就是浏览器在响应一个请求的时候,就突然不响应时间,进入假死状态,Cup也飙升到100%. 但是这个问题只出现在IE浏览器,chrome和Firefox等 ...

  2. async:false同步请求,浏览器假死

    // 异步请求导致数据错乱 // function get_num(){ // $("input[name='monitor']").eq(1).attr('checked',tr ...

  3. jQuery Ajax同步参数导致浏览器假死怎么办

    俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下.   事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的 ...

  4. js ajax同步请求造成浏览器假死的问题

    一.问题的起因 今天做一个需求遇到了这么个情况,就是用户个人中心有个功能,点击按钮,可以刷新用户当前的积分,这个肯定需要使用到ajax的同步请求了,当时喀喀喀三下五除二写玩了,大概代码如下: /** ...

  5. (转)优化js脚本设计,防止浏览器假死

    在Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出“脚本运行时间过长“的提示框,如果出现这种情况说明你的脚本已经失控了,必须进行优化. 为什么会出现这种情况呢,我们先来看一下浏览器的内 ...

  6. 优化js脚本设计,防止浏览器假死

    在Web开发的时候经常会遇到浏览器不响应事件进入假死状态,甚至弹出"脚本运行时间过长"的提示框,如果出现这种情况说明你的脚本已经失控了,必须进行优化. 为什么会出现这种情况呢,我们 ...

  7. AjaxPro实现异步调用,解决浏览器假死及超时问题

    平时使用AjaxPro的时候基本上非常easy var msg = UseClass.Method(argument).value; 由于后台响应比較慢,所以加了个"loading" ...

  8. jQuery Ajax async=>false异步改为同步时,导致浏览器假死的处理方法

    今天做一个需求遇到了这么个情况,就是用户个人中心有个功能,点击按钮,可以刷新用户当前的积分,这个肯定需要使用到ajax的同步请求了,当时喀喀喀三下五除二写玩了,大概代码如下: /** * 异步当前用户 ...

  9. 红米note3的wifi断流或假死

    红米note3的wifi断流/假死 日常使用note3的时,比如长时间浏览网页,点击一个链接会卡住不动,在等待十几秒之后才恢复.第一反应是不是网络不好?但是这种情况常常出现之后,对比其他的手机,比如价 ...

随机推荐

  1. 赵雅智_Fragment

    当我们须要动态的多界面切换的时候,就须要将UI元素和Activity融合成一个模块. 在2.3中我们一般通过各种Activity中进行跳转来实现多界面的跳转和单个界面动态改变.在4.0或以上系统中就能 ...

  2. R语言数据分析系列之五

    R语言数据分析系列之五 -- by comaple.zhang 本节来讨论一下R语言的基本图形展示,先来看一张效果图吧. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi ...

  3. Solaris服务管理

    远程登录协议 telnet \ssh 等.当然我们可以查看谁登录过我的系统,以及可以利用ftp记录日志. 一.SMF: 服务管理工具 优点:自动恢复意外终止的服务,支持服务的依赖关系,一个服务可以有多 ...

  4. yum安装zabbix监控

    公司的服务器由于没有监控软件监控,最感觉不安全,就开始研究zabbix的安装,最后找到一个最简单的安装方法,在这里记录一下,方便以后的查阅 1.安装zabbix官方的软件配置仓库 rpm -ivh h ...

  5. shell(3):文本处理、基本语法和脚本编写

    一.awk.变量.运算符.if多分支 awk:shell编辑器的一种文本处理工具/命令,同grep.sed一样均可解释正则.具体运用下面awk文本处理有详细说明. 变量:分为系统变量和临时变量.变量一 ...

  6. vs2012 MinGW 编译ffmeg 引用外部库libx264,librtmp

    VS2012如何编译ffmpeg前面已经有文章讲过,本来主要讲述如何引用外部库libx264,librtmp, ffmpeg版本是3.0.2. 1. 下载x264源文件并编译 源码地址是http:// ...

  7. 递归计算战士打靶S次打了N环一共同拥有多少种可能的问题

    问题描写叙述 一个战士打了10次靶.一共打了90环,问一共同拥有多少种可能,并输出这些可能的组合. 思路 首先.嵌套10层循环进行穷举是不可取的,一是由于速度太慢,二是假设改成打20次靶就完蛋了. 事 ...

  8. 文件I/O相关函数

    open()和openat()函数: #include <fcntl.h> // 成功返回文件描述符,出错返回-1 int open(const char *path, int oflag ...

  9. antd移动端onClick事件点击无效

    最近空余时间比较多,自己想学习react跟移动端的东西,就选用了antd-mobile库,框架搭好开发过程中遇到个问题,里面绑定的点击事件无效,不仅是antd自带的按钮无效,原生button点击也没反 ...

  10. Spring与JDK版本不一致引发问题Caused by: java.lang.IllegalArgumentException

    tomcat启动一个spring的项目,tomcat使用8.5,JDK使用1.8,Spring使用3.0,启动之后报错 Caused by: java.lang.IllegalArgumentExce ...