在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. Neural Networks for Machine Learning by Geoffrey Hinton (1~2)

    机器学习能良好解决的问题 识别模式 识别异常 预測 大脑工作模式 人类有个神经元,每一个包括个权重,带宽要远好于工作站. 神经元的不同类型 Linear (线性)神经元  Binary thresho ...

  2. openpyxl的使用记录

    脚本功能描述: 读取指定文件夹内的.xlsx文件,遍历提取整理信息保存到另一指定文件夹中 import openpyxl import os import shutil city='城市名' def ...

  3. Servlet 3.0的AsyncListener接口

    Servlet 3.0的AsyncListener接口 作者:chszs,转载需注明. 博客主页:http://blog.csdn.net/chszs 一.Servlet 3.0介绍 Servlet ...

  4. vue2.0 自定义过滤器

    2.0中已经废弃了过滤器,需要我们自定义 <div id="app"> {{message|uppercase}} </div> //过滤器 Vue.fil ...

  5. mediawiki 管理员/行政员设置

    mediawiki行政员找回 mediawiki 1.22.6默认安装完毕后,无管理员/行政员.默认都是user组成员.这样不便于wiki系统维护. 注: 默认情况下.行政员组(bureaucrat) ...

  6. mini2440使用jlink烧写superboot到norflash

    Jlink版本号:J-flash ARM V4.12                    J-Flash ARM的配置. 一般说来file-->open project里面会找到一些*.jfl ...

  7. 升级iOS8和iOS9系统后,保险箱Pro、私人保险箱、私密相冊打开就闪退的官方解决方式

    升级iOS8和iOS9.iOS10系统后,保险箱Pro.私人保险箱.私密相冊打开就闪退的官方解决方式 查看设备iOS操作系统版本号号办法:iPhone/iPad->设置->通用->关 ...

  8. 代写GIS系统

    代写GIS系统,熟悉arcgis,leaflet ,百度地图等api.可以提供系统代写,技术咨询等

  9. Object/Relational Mapping 数学关系 反面向对象

    [hibernate ORM 是对象关系映射框架 事实上的持久化存储引擎] http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/ ...

  10. for(String s:list)的运行

    源码 List<String> list = new ArrayList<>(); for (String s:list){ } class文件 List<String& ...