业务场景:
用户上传文件,点击上传,提示正在上传,请稍等,并且显示遮罩层,遮罩住整个页面,这里上传用得是异步上传。
问题:
当点击上传,没有触发遮罩层效果,而是在ajax执行完毕后才显示遮罩层。
原因:
浏览器中有两个引擎——JavaScript引擎和渲染引擎,它们对应了浏览器的两个线程。这两个引擎各司其职:
-
JavaScript引擎解析并执行JavaScript代码。
-
渲染引擎对界面进行绘制或者重绘(对DOM的渲染)。
在浏览器取得HTML文档并解析HTML的时候,浏览器会:
-
对DOM树进行解析。解析
<body>
中标签内容时,能形成渲染树,并渲染其中的元素。这个是在渲染引擎中做的。 -
遇到
<script>
标签时(注意解析HTML时遇到的script标签),基于JavaScript可能会修改DOM的考虑,其中的内容将会在此时被执行(如果是外部JS文件的代码,会先加载这个文件资源,这部分后面再表)。执行JavaScript代码是在JavaScript引擎中做的。
由于:
脚本执行和渲染DOM的并发可能会引发严重的冲突,
所以:
JavaScript引擎和渲染引擎所在的两个线程被设计为互斥的!
这就意味着:
在执行<script>
中内容时,浏览器会切换到JavaScript引擎所在的线程,此时渲染引擎所在的线程会阻塞,故其后元素的解析和渲染会暂停。
解决方案:
调用jQuery得show方法,把遮罩元素关联到show方法,jQuery的show方法回在执行完渲染在进行脚本的执行。
$("#zhezhao").show(function(){ var formData = new FormData($( "#uploadFile" )[0]); $.ajax({ url: 'url' , timeout:100000, type: 'POST', data: formData, async: false, cache: false, contentType: false, processData: false, success: function (returndata) { }, error: function (error) { }, complete : function(XMLHttpRequest,status){ //请求完成后最终执行参数 } }); });