单线程特点执行异步操作 

  js是单线程语言,浏览器只分配给js一个主线程,用来执行任务(函数),但一次只能执行一个任务,这些任务就会排队形成一个任务队列排队等候执行.一般而已,相对耗时的操作是要通过异步来进行加载,可以避免导致页面的假死.
setTimeout(function(){
     console.log(这是timeout事件回调);
},1000);
  JS阻塞renderdom的渲染,同一时间只能做一件事,避免了浏览器渲染DOM冲突,JS执行的时候,JS可以修改DOM,浏览器DOM渲染会停止,WebWorker支持多线程,但不能渲染DOM.

解决方案——异步

setTimeout(function(){
     console.log(这是timeout事件回调);
},1000);
  执行这段代码的时候,浏览器异步执行计时操作,传入setTimeout的函数会被暂存起来,当1000ms到了后,会触发定时事件,这个时候,就会把回调函数放到任务队列里,待所有程序执行完,处于空闲的状态时,会立马看看有没有暂存起来要执行的任务,整个程序就是通过这样的一个个事件驱动起来的,如下图1.1所示:
图1.1 工作原理图
  "任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等),例如onClick事件,只要指定这些事件的异步操作,就会进入任务队列中等待执行.
  其中JS实现异步是不断通过事件轮询(Event Loop)的方式实现的,同步代码直接执行,异步代码先放在异步队列中,等待同步代码执行完,轮询执行异步队列中的异步代码
  AJAX请求天气接口数据如下:
<script type="application/javascript" src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
<script type="application/javascript">
    function urlencode (str) {
        str = (str + '').toString();
        return encodeURIComponent(str).replace(/!/g, '%21').replace(/'/g, '%27').replace(/(/g, '%28').
        replace(/)/g, '%29').replace(/*/g, '%2A').replace(/%20/g, '+');
    }
   var city= '深圳',$citycode=urlencode(city);
   var url='http://v.juhe.cn/weather/index?format=2&cityname='+$citycode+'&key=c82727e986a4f6cfc6ba1984f1f9183a';
    $.ajax({url: url,
        dataType: "jsonp",
        type:"get",
        data:{location:city},
        success:function(data) {
            var sk = data.result.sk;
            var today = data.result.today;
            var futur = data.result.future;
            var fut = "日期温度天气风向";
            $('#mufeng').html(
                "<p>" + '当前: ' + sk.temp + '℃ , ' + sk.wind_direction + sk.wind_strength +
                ' , ' + '空气湿度' + sk.humidity + ' , 更新时间' + sk.time +
                "</p><p style='padding-bottom: 10px;'>" + today.city + ' 今天是: ' + today.date_y +
                ' ' + today.week + ' , ' + today.temperature + ' , ' + today.weather + ' , ' + today.wind + "<p></p>"
            );
        }});

</script>

结果如下所示:先打印cc1,cc222, 然后执行25行success中代码

问题

  1. Callback没有按照我们预期的顺序执行
  2. Callback不易于我们进行模块化管理

jQuery.Deferred

jQuery1.5的变化,语法糖改变,遵循开发封闭原则

$.ajax({url: url,
        dataType: "jsonp",
        type:"get",
        data:{location:city}})
        .done(function(data){
            if(data.result){
                var sk = data.result.sk;
                var today = data.result.today;
                var futur = data.result.future;
                var fut = "日期温度天气风向";
                $('#mufeng').html(
                    "<p>" + '当前: ' + sk.temp + '℃ , ' + sk.wind_direction + sk.wind_strength +
                    ' , ' + '空气湿度' + sk.humidity + ' , 更新时间' + sk.time +
                    "</p><p style='padding-bottom: 10px;'>" + today.city + ' 今天是: ' + today.date_y +
                    ' ' + today.week + ' , ' + today.temperature + ' , ' + today.weather + ' , ' + today.wind + "<p></p>"
                );
            }else {
                console.log('该接口调用达到上限')
            }
        })
        .fail(function(){
            console.log("获取数据失败")
        })
        .done(function(data){
            console.log(data)
        })

Deferred的另一种写法:

$.ajax({url: url,
        dataType: "jsonp",
        type:"get",
        data:{location:city}})
        .then(function(data){
            if(data.result){
                var sk = data.result.sk;
                var today = data.result.today;
                var futur = data.result.future;
                var fut = "日期温度天气风向";
                $('#mufeng').html(
                    "<p>" + '当前: ' + sk.temp + '℃ , ' + sk.wind_direction + sk.wind_strength +
                    ' , ' + '空气湿度' + sk.humidity + ' , 更新时间' + sk.time +
                    "</p><p style='padding-bottom: 10px;'>" + today.city + ' 今天是: ' + today.date_y +
                    ' ' + today.week + ' , ' + today.temperature + ' , ' + today.weather + ' , ' + today.wind + "<p></p>"
                );
            }else {
                console.log('该接口调用达到上限')
            }
        },function(){
            console.log("获取数据失败1")
        })
        .then(function(data){
            console.log(data);
        },function(){
            console.log("获取数据失败2")
        })

执行结果如下图所示:

 

 $.Defferred 对象封装 返回一个defferred对象

    function waitHandleWeather() {
        var dtd = $.Deferred()
        var wait =function(dtd){
            $.ajax({url: url,
                dataType: "jsonp",
                type:"get",
                data:{location:city}})
                .then(function(data){
                    dtd.resolve(data)
                },function(){
                    dtd.reject('该接口调用达到上限') //返回promise对象,如果返回dtd,外面就可以修改dtd的操作,不安全
                });
            return dtd.promise();
        }
        return wait(dtd); //返回promise对象
    }
    var weatherDataDeferred = waitHandleWeather();
    $.when(weatherDataDeferred).then(function(data){
        if(data.result){
            var sk = data.result.sk;
            var today = data.result.today;
            var futur = data.result.future;
            var fut = "日期温度天气风向";
            $('#mufeng').html(
                "<p>" + '当前: ' + sk.temp + '℃ , ' + sk.wind_direction + sk.wind_strength +
                ' , ' + '空气湿度' + sk.humidity + ' , 更新时间' + sk.time +
                "</p><p style='padding-bottom: 10px;'>" + today.city + ' 今天是: ' + today.date_y +
                ' ' + today.week + ' , ' + today.temperature + ' , ' + today.weather + ' , ' + today.wind + "<p></p>"
            );
        }else {
            console.log('该接口调用达到上限')
        }
    },function(err){
        console.log(err)
    });

同步和异步的区别

  同步在执行的过程会阻塞I/O,在正常的流程中执行的顺序不同,例如setTimeout、setInterval,会改变流程执行的顺序,尽管setTimeout的time延迟时间为0,其中的function也会被放入一个队列中,等待下一个机会执行,当前的代码(指不需要加入队列中的程序)必须在该队列的程序完成之前完成,因此结果可能不与预期结果相同。因此,异步能改变流程执行的顺序,同步不会改变流程执行的顺序,依次执行.
 

jQuery.Deferred和Promise 区别

Promise不能主动干预改变promise的结果,Deffrred可以去改变干预执行的结果

 

最后,如果想看promise相关内容,请移步https://www.cnblogs.com/fuGuy/p/9215884.html

 

内容来源于网络如有侵权请私信删除
你还没有登录,请先登录注册
  • 还没有人评论,欢迎说说您的想法!