从进度条和alert的出现顺序来了解浏览器 UI 渲染 & JS进程

项目里有一个需求是在上传文件的时候需要显示进度条,那么理所当然的在上传完成后就需要提示用户上传完毕并且更新进度条。

之前的预期表现是,上传完毕后,先更新进度条到100%,再alert出提示,所以代码如下。

 $('progressBar').text('100%');
$('progressBar bar').css('width', '100%');
alert('上传成功');

问题一:实际表现为先alert出提示,此时被阻塞的页面显示的进度条没有被更新到100%。

分析原因,浏览器UI渲染和JS执行共用同一个线程,在这段代码里,实际上第1、2行的代码的确已经被执行了,但是还有第3行的JS代码需要执行,也就是JS任务仍未完成,所以线程仍然被JS占用,导致已经被执行的UI修改需要等到JS任务结束后才能够使用线程刷新页面。而alert在没有被用户关闭之前JS任务会一直占用线程,导致alert弹出框后的进度条未被更新。

解决:通过setTimeout可以模拟出另外一个JS任务,简称这个新的JS任务为t2,原来的JS任务为t1。

它独立于当前的JS任务,所以在第3行运行完,将alert放在等待队列后,t1就让出线程,此时第2行修改了的UI渲染就先占用线程,完成UI的重新渲染,让出线程,再由t2占用线程执行alert。

 $('progressBar').text('100%');
$('progressBar bar').css('width', '100%');
setTimeout(function() { alert('上传成功'); }, 100);

需要注意的是,如果实现进度条更新后马上弹出提示框,需要将setTimeout的等待时间调整到1000ms以内,一般来说10~100ms比较合适,时间差不要让用户感受到其中的间隔就可以了。

问题二:解决了一直留在上传页面alert和进度条的顺序问题,又发现上传过程中切换到其他标签页时,alert强制跳回上传页面的时候进度条仍然没有被更新。

目前估计问题处在标签页未被选中/激活的时候,线程的轮询暂停的原因。但是这时候JS的setTimeout仍然会运行,所以具体原因仍然需要确定……

TBC.

上一篇:C#编程(六十六)----------表达式树总结


下一篇:Mybatis-plus的分页查询SelectPage总是查询所有