认识jQuery的Promise

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

打开浏览器的控制台先。ajax

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

数组

运行结果:promise

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

玩玩Deferred:dom

<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:spa

<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>

code

咱们发现:

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

二、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一致。

相关文章
相关标签/搜索