认识jQuery的Promise的具体使用方法
先前了解了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一致。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。