以jQuery中$.Deferred对象为例讲解promise对象是如何处理异步问题
Promises是一种令代码异步行为更加优雅的抽象,它很有可能是JavaScript的下一个编程范式,一个Promise即表示任务结果,无论该任务是否完成。
在一些现代浏览器中已经提供了原生的Promise对象,其遵循Promise/A+标准。在jQuery1.5+,提供了$.Deferred(其可以被转化为promise对象)。很多知名的框架中,也提供了promise对象。promise对象在javascript中已经是一种很重要的模式,它在解决异步问题时表现出的优雅,正是javascript所需要的。以下以jQuery中的$.Deferred对象为例,来看一下promise对象是如何处理异步问题。关于$.Deferred对象,可以到jQuery官网查看,这里就不赘述了。
一、封装异步操作
首先,我们以加载图片为例,看以下代码:
//加载图片函数 var loadImg = function(url){ var img = new Image() , deferred = $.Deferred() ; img.src = url ; img.onload = function(){ //成功则触发deferred.resolve deferred.resolve( this ) ; } ; img.onerror = function(e){ //失败则触发deferred.reject deferred.reject( e ); } ; //返回promise对象 return deferred.promise() ; } ; //请求图片 var request = loadImg('http://r2.ykimg.com/0515000054AFFC2D6737B343930AFAD6') ; //请求成功 request.done(function(img){ //code }) ; //可以注册多个回调,当请求成功时,会按注册的顺序执行,fail和always也有此性质 request.done(function(img){ // code }); //请求失败 request.fail(function(){ // code }) ; //请求完毕 request.always(function(){ //code });
以上的代码,我封装了图片加载的操作,将他们委托给$.Deferred,最后生成一个promise返回。使用这样的方式,相比用对外暴露回调的方式,显得更干净、更清晰。这么做的另一个更重要的原因是,promise的连接。
二、promise的连接
我们还是以上面图片加载的代码为例,来看一下如何做promise的连接,看以下代码:
var request = loadImg('http://b1.hucdn.com/upload/item/1411/13/89613257775992_800x800.jpg') ; request.done(function(img){ //code }) ; //request连接别的promise之后返回的promise var request3 = request.then(function(img){ //request执行成功时 连接request1 var request1 = loadImg('http://b1.hucdn.com/upload/item/1410/19/29492535741725_800x800.jpg') ; return request1 ; },function(e){ //request执行失败时 连接request2 var request2 = loadImg('http://b1.hucdn.com/upload/item/1410/19/29492535741725_800x800.jpg') ; return request2 ; }); //request执行并且request1或request2成功执行时 request3.done(function(done){ //code }) ;
promise对象提供了then的方法,它接受两个回调:onResolve和onReject,在回调中返回promise,就可以完成promise之间的连接。通过这种方式,可以使异步操作串行的执行。
同时,jQuery还提供了另外一种连接方式,看代码:
var request = loadImg('http://b1.hucdn.com/upload/item/1412/23/48188827139381_800x800.jpg') ; var request1 = loadImg('http://b1.hucdn.com/upload/item/1412/06/50258594673502_800x800.jpg') ; //通过$.when连接promise var request2 = $.when(request,request1) ; request2.done(function(img,img){ //code }) ;
jQuery中提供了$.when这个函数,它可以接受n个promise对象为参数,它是将promise的执行结果连接在一起。使用这种方式,多个异步操作可以并行执行。
三、The End
这里的代码是以加载图片为例,同样的做法可以应用到其他的异步操作中去。比如jQuery中的$.ajax、$.fn.animate,调用它们返回的就是promise。在node端,也可以把一些异步操作(读数据库、读文件等)封装成promise。继而对多个promise实现合并的操作,使其串行或者并行执行。
附:deferred对象
deferred除了用于转化promise对象外,本身也是个很有用的对象。它除了提供像promise对象的那些方法和属性外,还有notify函数和progress函数,这两个函数在实现进度条和瀑布流的时候,有很大的用处。
在实现进度条时,resolve和done函数可以用于定义进度条读取到100%时的触发时机和触发逻辑,notify和progress函数可以用于定义进度条在读取中的触发时机和触发逻辑。reject和fail函数可以用于定义进度读取失败时的触发时机和触发逻辑。
在实现瀑布流时,resolve和done函数可以用于定义当数据已经全部加载到页面的触发时机和触发逻辑,notify和progress函数可以用于定义瀑布流读取下一页的触发时机和触发逻辑。
相关文章
浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法
本篇文章主要是对jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助2014-01-01JQuery判断正整数整理小结(jQuery 文本框中只能输入正整数)
这篇文章主要介绍了JQuery判断正整数,附上详细的代码供大家查看具体的方法,需要的朋友可以参考下2017-08-08基于jQuery的网页右下角弹出广告(IE7,firefox)
以前曾写过一个,不过太麻烦了,呵呵```现在改进了一下,其实很简单:css定位层一直在右下角,用js控制层的高度增减。2010-08-08JQuery中对Select的option项的添加、删除、取值
jQuery获取Select选择的Text和Value及添加/删除Select的Option项,在本文将为大家详细介绍下具体的实现,感兴趣的朋友可以参考下2013-08-08
最新评论