浏览器中的JS线程和UI线程以列队的形式同步执行的,原因是s是可操纵DOM的,如果在修改这些元素属性同时渲染界面(即JS线程和UI线程同时运行),那么渲染线程前后获得的元素数据就可能不一致了。因此为了防止渲染出现不可预期的结果,这里所谓的伪异步,是指在执行js代码的同时能达到UI渲染的效果。
例如我们点击一个按钮然后js有一段很复杂的计算,我们希望在计算的过程中能够有一个正在执行的动画来提高用户体验,我们以下面的代码来写的时候,其实是不可行的。
//显示加载动画
utils.loading();
//耗时操作
for(var i=0;i<100;i++){
console.log(11);
}
//关闭加载动画
utils.closeload();
原因就是上面说的js线程和UI线程是同步执行的,在js
引擎运行脚本期间,浏览器渲染线程都是处于挂起状态的,也就是说被”冻结”了,而我们可以用
setTimeout方法来实习伪异步,因为setTimeout执行时会新开一个定时器线程,这是正好处于JS线程运行当中,当JS线程执行完成后,发现setTimeout马上就要开始执行(即时间小于上述的临界值),为了避免UI线程运行时间太长而带来的setTimeout严重拖时的不好体验,浏览器选择一直等待直到setTimeout到期,然后运行里面的js。如果发现setTimeout还要隔较长时间才到期,为了避免时间上的浪费,浏览器选择马上切换到UI线程。因此设定setTimeout大一点(大于100ms便可)时,便会有时间切换成UI线程进行UI渲染,类似如下代码。
//显示加载动画
utils.loading();
//让JS线程等待100毫秒,等待会让UI渲染进程实现,
//如果发现setTimeout还要隔较长时间才到期,为了避免时间上的浪费,浏览器选择马上切换到UI线程。
setTimeout(function(){
//长时间的js计算,同步请求等耗时操作
for(var i=0;i<100;i++){
console.log(11);
}
//关闭加载动画
utils.closeload();
},1000);