以jQuery中$.Deferred对象为例讲解promise对象是如何处理异步问题


Posted in Javascript onNovember 13, 2015

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函数可以用于定义瀑布流读取下一页的触发时机和触发逻辑。

Javascript 相关文章推荐
在线游戏大家来找茬II
Sep 30 Javascript
使用Jquery来实现可以输入值的下拉选单 雏型
Dec 06 Javascript
浏览器解析js生成的html出现样式问题的解决方法
Apr 16 Javascript
jquery的ajax跨域请求原理和示例
May 08 Javascript
BootStrap下jQuery自动完成的样式调整
May 30 Javascript
AngularJS基础 ng-copy 指令实例代码
Aug 01 Javascript
ES6新特征数字、数组、字符串
Oct 01 Javascript
JS 调试中常见的报错问题解决方法
May 20 Javascript
Vue scrollBehavior 滚动行为实现后退页面显示在上次浏览的位置
May 27 Javascript
微信小程序模板消息限制实现无限制主动推送的示例代码
Aug 27 Javascript
解决vue-cli 打包后自定义动画未执行的问题
Nov 12 Javascript
使用 JavaScript 制作页面效果
Apr 21 Javascript
Jquery promise实现一张一张加载图片
Nov 13 #Javascript
jquery转盘抽奖功能实现
Nov 13 #Javascript
javascript生成随机数方法汇总
Nov 12 #Javascript
js正则表达式验证邮件地址
Nov 12 #Javascript
每天一篇javascript学习小结(Boolean对象)
Nov 12 #Javascript
为何JS操作的href都是javascript:void(0);呢
Nov 12 #Javascript
基于jquery实现左右按钮点击的图片切换效果
Jan 27 #Javascript
You might like
php 字符串替换的方法
2012/01/10 PHP
PHP内核探索之变量
2015/12/22 PHP
利用PHP_XLSXWriter代替PHPExcel的方法示例
2017/07/16 PHP
微信公众号开发之获取位置信息php代码
2018/06/13 PHP
[原创]网络复制内容时常用的正则+editplus
2006/11/30 Javascript
JavaScript中获取样式的原生方法小结
2014/10/08 Javascript
JavaScript italics方法入门实例(把字符串显示为斜体)
2014/10/17 Javascript
JS运动基础框架实例分析
2015/03/03 Javascript
使用jquery制作弹出框效果
2015/04/03 Javascript
浅析Bootstrap验证控件的使用
2016/06/23 Javascript
用自定义图片代替原生checkbox实现全选,删除以及提交的方法
2016/10/18 Javascript
bootstrap table小案例
2016/10/21 Javascript
javascript垃圾收集机制的原理分析
2016/12/08 Javascript
Javascript 对cookie操作详解及实例
2016/12/29 Javascript
微信小程序swiper禁止用户手动滑动代码实例
2019/08/23 Javascript
[43:41]OG vs Newbee 2019国际邀请赛淘汰赛 胜者组 BO3 第一场 8.21.mp4
2020/07/19 DOTA
Django中的CACHE_BACKEND参数和站点级Cache设置
2015/07/23 Python
python用reduce和map把字符串转为数字的方法
2016/12/19 Python
Python实现繁体中文与简体中文相互转换的方法示例
2018/12/18 Python
python 用下标截取字符串的实例
2018/12/25 Python
python实现两个dict合并与计算操作示例
2019/07/01 Python
用python解压分析jar包实例
2020/01/16 Python
Pycharm 使用 Pipenv 新建的虚拟环境(图文详解)
2020/04/16 Python
Python 数据分析之逐块读取文本的实现
2020/12/14 Python
美国按摩椅批发网站:Titan Chair
2018/12/27 全球购物
美国家居装饰店:Pier 1
2019/09/04 全球购物
C/C++有关内存的思考题
2015/12/04 面试题
应用电子专业学生的自我评价
2013/10/16 职场文书
文史专业毕业生自荐信
2013/11/17 职场文书
翻译专业应届生求职信
2013/11/23 职场文书
工程管理专业毕业生自荐信
2014/01/24 职场文书
元宵晚会主持词
2014/03/25 职场文书
乐山大佛导游词
2015/02/02 职场文书
2015年体育教学工作总结
2015/05/20 职场文书
太空授课观后感
2015/06/17 职场文书
教你使用Python获取QQ音乐某个歌手的歌单
2022/04/03 Python