同步请求和GUI渲染阻塞问题

2019-05-09  本文已影响0人  喵呜Yuri

在jquery中ajax请求一半情况下使用异步执行,单有时也会又特殊需求使用同步,此时如果想要诸如显示loading等待框,执行请求,关闭loading等待框时就会出现问题。首先loading等待框居然不出现,
原因是这样的:
原因就是ajax的async设置为true时,ajax会委托浏览器另起一个线程,此线程与js线程和ui线程不冲突,只是在执行完成后再插入js事件环。而ajax的async设置为false时并没有启动单独的线程,还是在js主线程中执行,所以会与浏览器的渲染(UI)线程和js线程是互斥的,在执行js耗时操作时,页面渲染会被阻塞掉。当我们执行异步ajax的时候没有问题,但当设置为同步请求时,其他的动作(ajax函数后面的代码,还有渲染线程)都会停止下来。即使我的DOM操作语句是在发起请求的前一句,这个同步请求也会“迅速”将UI线程阻塞,不给它执行的时间。这就是代码失效的原因。

这时使用settimeout也是不可行的,因为setTimeout并不是异步的,而是将其操作插入到js线程中,排队执行,造成异步的假象。
正确的解决方法是使用#######deferred
举个简单的小例子
使用前:

function toGetData() {
       var defer = $.Deferred();
       $.ajax({
           url: ' https://api.itooi.cn/music/tencent/search?key=579621905&s=123&limit=10&offset=0&type=song',
           type: "get", // 请求类型
           dataType: 'json',
           async: true, // 是否异步
           success: function (ret) {
              console.log('2');
           }
       });
       return defer;
   }
  $('button').click(function(){
       $(".shadow").show()
       console.log('1');
       toGetData();
       console.log('3');
   })

依次输出1,3,2
使用后:

    function toGetData() {
        var defer = $.Deferred();
        $.ajax({
            url: ' https://api.itooi.cn/music/tencent/search?key=579621905&s=123&limit=10&offset=0&type=song',
            type: "get", // 请求类型
            dataType: 'json',
            async: true, // 是否异步
            success: function (ret) {
               console.log('2');
                defer.resolve(ret)
            }
        });
        return defer;
    }
    $('button').click(function(){
        $(".shadow").show()
        console.log('1');
        $.when(toGetData()).done(function(ret){
            $(".shodow").hide();
            console.log('3');
        });
    })

依次输出1,2,3

上一篇 下一篇

猜你喜欢

热点阅读