jQuery同步Ajax带来的UI线程阻塞问题

一、需求

在调ajax接口的时候因为有时间延迟,想要做一个loading加载的效果,等数据返回时再把loading的效果去掉。

所以我在调ajax的代码块前面加了显示loading效果的代码,ajax结束返回之后加了隐藏loading效果的代码。然后都没有起作用。

二、遇到问题

在ajax请求前后,对页面的样式进行操作不起效果。

浏览器的渲染(UI)线程和js线程是互斥的,在执行js耗时操作时,页面渲染会被阻塞掉。当我们执行异步ajax的时候没有问题,但当设置为同步请求时,其他的动作(ajax函数后面的代码,还有渲染线程)都会停止下来。即使我的DOM操作语句是在发起请求的前一句,这个同步请求也会“迅速”将UI线程阻塞,不给它执行的时间。这就是代码失效的原因。

 

三、解决方法

详细参考:https://www.cnblogs.com/lvdabao/p/3744030.html,作者和我遇到的问题完全一致

1.我们在bxcommmon里面封装的ajaxRequest,默认ajax是同步,第一步要先将ajaxRequest设置为异步(最后一个参数设置为true)

  AjaxCommunicator.ajaxRequest(url, "POST", paramJsonObj, callback,true);

2.引入deferred对象

  jQuery的deferred对象详解: http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html

3. 引入$.when()函数

  JQuery when(deferreds)方法 的使用:https://www.cnblogs.com/lvjiaqin/p/6814052.html

贴一下解决代码:

 

总之,想让ajax走完再加载页面,就要使用同步。但是只要同步,ajax就会阻塞ui线程,使得loading显示不出来。

只有使用了deffer对象和$.when(),既可以ajax设为异步,保证了loading的正常显示,又可以保证在ajax走完再加载页面。因为$.when().done()会在deffer.resolve()之前的代码全部走完后才走done中的代码。

$.when()函数只接受defferred对象,所以我们在处理ajax的函数中需要先创建defferred对象,再return就解决了。defer.resolve(ret)用于控制ajax何时结束,比如我执行完赋值操作结束ajax,进入$.when().done()中的回调函数,它还可以把数据也带出来使用。类似的,还存在一个deferred.reject()方法,作用是将dtd对象的执行状态从"未完成"改为"已失败",从而触发$.when().fail()方法。

 

posted @ 2018-06-21 10:12  Evaxtt  阅读(952)  评论(0编辑  收藏  举报