从setTimeout到浏览器线程机制 ,实现JS线程和UI同时执行的效果

遇到一个问题情况:

ocx读取多条记录的结果集。

在js里用 for遍历。

for(var i= 0;i<length;i++){

     $.ajax({

       后台返回结果

       处理成功,

       调用更新进度条的方法。

     })

}

发现,总是当for全部遍历完成,才去渲染进度条控件。更改样式。

查阅N多资料更改后,

将for改为递归调用,没执行一次,渲染一次进度条,后面的JS代码放在setTimeout(function,0),这时浏览器会优先渲染UI界面,然后在执行后面的JS代码,就实现了进度条实时更新了。

 

 

//更新进度条的数据
run(size,a+1);
if(a<size-1){
++a;
//让JS线程等待100,等待会让UI渲染进程实现
setTimeout(submitData,10);
//submitData();
}else{
size = 0;
a= 0;
return ;
}

解决问题知识点:从setTimeout到浏览器线程机制 

我们知道浏览器内部至少会有这么两个线程:解析js的线程和渲染界面的线程。这里我们暂且称它们为JS线程和UI线程。

由于js是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JS线程和UI线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。因此为了防止渲染出现不可预期的结果,浏览器控制JS线程和UI线程以列队的形式同步执行。

setTimeout执行时会新开一个定时器线程,这是正好处于JS线程运行当中,当JS线程执行完成后,发现setTimeout马上就要开始执行(即时间小于上述的临界值),为了避免UI线程运行时间太长而带来的setTimeout严重拖时的不好体验,浏览器选择一直等待直到setTimeout到期,然后运行里面的js。如果发现setTimeout还要隔较长时间才到期,为了避免时间上的浪费,浏览器选择马上切换到UI线程。 

结论:setTimeout 可用于处理耗时的js代码,但千万要小心第二个参数不要设置太小了,否则你看到的同样是一个空白页面。推荐在100ms左右,可满足所有浏览器。当然,如果可以不兼容IE的话,抛弃setTimeout吧,web workers 会是个很好的选择。

posted @ 2016-04-25 17:23  红色柠檬  阅读(6354)  评论(1编辑  收藏  举报