• jQuery的Promise


    原文电梯:https://www.cnblogs.com/yelongsan/p/7644239.html

    先前了解了ES6的Promise对象,来看看jQuery中的Promise,也就是jQuery的Deferred对象。

    打开浏览器的控制台先。

    <script>
        var defer = $.Deferred();
        console.log(defer);
    </script>

    运行结果:

    和ES6的Promise对象长的有点像,jQuery的Deferred对象也有resolve、reject、then方法,还有done、fail、always......方法。jQuery就是用这个Deferred对象来注册异步操作的回调函数,修改并传递异步操作的状态。

    玩玩Deferred:

    复制代码
    <script>
        function runAsync(){
            var defer = $.Deferred();
            //做一些异步操作
            setTimeout(function(){
                console.log('执行完成');
                defer.resolve('异步请求成功之后返回的数据');
            }, 1000);
            return defer;
        }
        runAsync().then(function(data){
            console.log(data)
        });
    </script>
    复制代码

     运行之后,Deferred对象的实例defer通过resolve方法把参数 “异步请求成功之后返回的数据” 传回到then方法中进行接收,,打印。

    和ES6的Promise相似,但是有一点点区别,再看下Promise:

    复制代码
    <script>
        function runAsync(){
            var p = new Promise(function(resolve, reject){
               
                setTimeout(function(){
                    console.log('执行完成');
                    resolve('异步请求成功之后返回的数据');
                }, 1000);
            });
            return p;            
        }
    
        runAsync().then(function(data){
            console.log(data);
        });
    </script>
    复制代码

    我们发现:

    1、创建Deferred对象的时候没有传参;而创建Promise对象的时候,传了参数(传了一个匿名函数,函数也有两个参数:resolve、reject);

    2、Deferred对象直接调用了resolve方法;而Promise对象则是在内部调用的resolve方法;

    说明:Deferred对象本身就有resolve方法,而Promise对象是在构造器中通过执行resolve方法,给Promise对象赋上了执行结果的状态。

    这样就有一个弊端:因为Deferred对象自带resolve方法,拿到Deferred对象之后,就可以随时调用resolve方法,其状态可以进行手动干预了

    复制代码
    <script>
        function runAsync(){
            var defer = $.Deferred();
            //做一些异步操作
            setTimeout(function(){
                console.log('执行完成');
                defer.resolve('异步请求成功之后返回的数据');
            }, 1000);
            return defer;
        }
       var der = runAsync();
       der.then(function(data){
            console.log(data)
       });
       der.resolve('在外部结束'); 
    </script>
    复制代码

     这样的话就直接在外部直接给Deferred设置了状态,打印“在外部结束”,1s后打印“执行完成”,不会打印“异步请求成功之后返回的数据”了。

    显然,这不好。我发个异步请求,还没收到数据就让人在外部给我结束了。。。。。。。

    当然这个坑jQuery肯定会填的,在Deferred对象上有一个promise方法,是一个受限的Deferred对象

    复制代码
    <script>
        function runAsync(){
            var def = $.Deferred();
            //做一些异步操作
            setTimeout(function(){
                console.log('执行完成');
                def.resolve('请求成功之后返回的数据');
            }, 2000);
            return def.promise(); //就在这里调用
        }
    </script>
    复制代码

    所谓受限的Deferred对象,就是没有resolve和reject方法的Deferred对象。这样就无法在外边改变Deferred对象的状态了。

    Deferred对象的then方法和done、fail语法糖

    我们知道,在ES6的Promise规范中,then方法接受两个参数,分别是执行完成和执行失败的回调,而jquery中进行了增强,还可以接受第三个参数,就是在pending状态时的回调,如下:

    deferred.then( doneFilter [, failFilter ] [, progressFilter ] )

    then方法

    复制代码
    <script>
        function runAsync(){
            var def = $.Deferred();
            //做一些异步操作
            setTimeout(function(){
                  var num = Math.ceil(Math.random()*10); //生成1-10的随机数
                   if(num<=5){
                       def.resolve(num);
                   }
                   else{
                       def.reject('数字太大了');
                   }
            }, 2000);
            return def.promise(); //就在这里调用
        }
    
        runAsync().then(function(d){
            console.log("resolve");
            console.log(d);
        },function(d){
            console.log("reject");
            console.log(d);
        })
    
    </script>
    复制代码

    Deferred对象的then方法也是可以进行链式操作的。

    done,fail语法糖,分别用来指定执行完成和执行失败的回调,与这段代码是等价的:

    复制代码
    <script>
        function runAsync(){
            var def = $.Deferred();
            //做一些异步操作
            setTimeout(function(){
                  var num = Math.ceil(Math.random()*10); //生成1-10的随机数
                   if(num<=5){
                       def.resolve(num);
                   }
                   else{
                       def.reject('数字太大了');
                   }
            }, 2000);
            return def.promise(); //就在这里调用
        }
    
        runAsync().done(function(d){
            console.log("resolve");
            console.log(d);
        }).fail(function(d){
            console.log("reject");
            console.log(d);
        })
    
    </script>
    复制代码

    always的用法

    jquery的Deferred对象上还有一个always方法,不论执行完成还是执行失败,always都会执行,有点类似ajax中的complete。

    $.when的用法

    jquery中,还有一个$.when方法来实现Promise,与ES6中的all方法功能一样,并行执行异步操作,在所有的异步操作执行完后才执行回调函数。不过$.when并没有定义在$.Deferred中,看名字就知道,$.when,它是一个单独的方法。与ES6的all的参数稍有区别,它接受的并不是数组,而是多个Deferred对象,如下:

    复制代码
    <script>
     function runAsync(){
            var def = $.Deferred();
            //做一些异步操作
            setTimeout(function(){
                  var num = Math.ceil(Math.random()*10); //生成1-10的随机数
                  def.resolve(num);   
            }, 2000);
            return def.promise(); //就在这里调用
        }
        $.when(runAsync(), runAsync(), runAsync()) .then(function(data1, data2, data3){
         console.log('全部执行完成');
         console.log(data1, data2, data3);
      });
    </script>
    复制代码

    jquery中没有像ES6中的race方法吗?就是以跑的快的为准的那个方法。对的,jquery中没有。
    以上就是jquery中Deferred对象的常用方法了。
     
    在上一篇和本篇当中,都是用一次性定时器来代替了异步请求进行数据处理。为什么没用ajax呢,不是因为麻烦,在这里要说一下ajax和Deferred的联系:
    jquery的ajax返回一个受限的Deferred对象,也就是没有resolve方法和reject方法,不能从外部改变状态,既然是Deferred对象,那么我们上面讲到的所有特性,ajax也都是可以用的。比如链式调用,连续发送多个请求:
    复制代码
    <script>
    req1 = function(){
        return $.ajax(/* **** */);
    }
    req2 = function(){
        return $.ajax(/* **** */);
    }
    req3 = function(){ 
      return $.ajax(/* **** */);
    }
    req1().then(req2).then(req3).done(function(){ console.log('请求发送完毕'); });
    </script>
    复制代码

    success、error与complete

    这三个方法是我们常用的ajax语法糖。

    $.ajax(/*...*/)
    .success(function(){/*...*/})
    .error(function(){/*...*/})
    .complete(function(){/*...*/})

    有时候比较喜欢在内部作为属性来处理。

    分别表示ajax请求成功、失败、结束的回调。这三个方法与Deferred又是什么关系呢?其实就是语法糖,success对应done,error对应fail,complete对应always,就这样,只是为了与ajax的参数名字上保持一致而已。

    总结:

    $.Deferred实现了Promise规范,then、done、fail、always是Deferred对象的方法。$.when是一个全局的方法,用来并行运行多个异步任务,与ES6的all是一个功能。ajax返回一个受限的Deferred对象,success、error、complete是ajax提供的语法糖,功能与Deferred对象的done、fail、always一致。

  • 相关阅读:
    jQuery UI draggable+droppable+resizable+selectable+sortable
    jQuery获取Select选择的Text和 Value(转)
    跨终端跨域的存储方案
    innerHTML 的坑
    几种Css前端框架资料
    分享一个前端框架 builive
    为什么要使用CDN?
    AliCDN,盛开在云端的花朵
    java 和 C# 的访问权限
    线程queue 事件event 协程
  • 原文地址:https://www.cnblogs.com/yjf713/p/13412155.html
Copyright © 2020-2023  润新知