以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 相关文章推荐
多浏览器兼容的获取元素和鼠标的位置的js代码
Dec 15 Javascript
javascript向后台传送相同属性的参数即数组参数
Feb 17 Javascript
AngularJS的一些基本样式初窥
Jul 27 Javascript
Bootstrap所支持的表单控件实例详解
May 16 Javascript
js改变html的原有内容实现方法
Oct 05 Javascript
利用jquery正则表达式在页面验证url网址输入是否正确
Apr 04 jQuery
vue实现仿淘宝结账页面实例代码
Nov 08 Javascript
vue axios 在页面切换时中断请求方法 ajax
Mar 05 Javascript
ES6 Iterator接口和for...of循环用法分析
Jul 31 Javascript
js瀑布流布局的实现
Jun 28 Javascript
Json实现传值到后台代码实例
Jun 30 Javascript
JS实现简易贪吃蛇游戏
Aug 24 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/02/04 PHP
php日期转时间戳,指定日期转换成时间戳
2012/07/17 PHP
解析zend studio中直接导入svn中的项目的方法步骤
2013/06/21 PHP
PHP编程开发怎么提高编程效率 提高PHP编程技术
2015/11/09 PHP
PHP+apc+ajax实现的ajax_upload上传进度条代码
2016/01/25 PHP
php实现计算百度地图坐标之间距离的方法
2016/05/05 PHP
php实现的一段简单概率相关代码
2016/05/30 PHP
php图像处理函数imagecopyresampled用法详解
2016/12/02 PHP
LAMP环境使用Composer安装Laravel的方法
2017/03/25 PHP
jQuery 获取对象 根据属性、内容匹配, 还有表单元素匹配
2010/05/31 Javascript
JQuery写动态树示例代码
2013/07/31 Javascript
JavaScript中json使用自己总结
2013/08/13 Javascript
使用Chrome调试JavaScript的断点设置和调试技巧
2014/12/16 Javascript
JScript中的条件注释详解
2015/04/24 Javascript
莱鸟介绍javascript onclick事件
2016/01/06 Javascript
ES6新特性之解构、参数、模块和记号用法示例
2017/04/01 Javascript
原生JS实现层叠轮播图
2017/05/17 Javascript
Vue-Router基础学习笔记(小结)
2018/10/15 Javascript
JS函数动态传递参数的方法分析【基于arguments对象】
2019/06/05 Javascript
vue中监听返回键问题
2019/08/28 Javascript
Vue 实现CLI 3.0 + momentjs + lodash打包时优化
2019/11/13 Javascript
[01:14]辉夜杯战队访谈宣传片—NEWBEE.Y
2015/12/26 DOTA
python 实现一个贴吧图片爬虫的示例
2017/10/12 Python
python xlsxwriter创建excel图表的方法
2018/06/11 Python
使用Python中tkinter库简单gui界面制作及打包成exe的操作方法(二)
2020/10/12 Python
Python使用struct处理二进制(pack和unpack用法)
2020/11/12 Python
python推导式的使用方法实例
2021/02/28 Python
施华洛世奇天猫官方旗舰店:SWAROVSKI
2017/04/17 全球购物
澳大利亚礼品篮网站:Macarthur Baskets
2019/10/14 全球购物
社区党总支书记先进事迹材料
2014/01/24 职场文书
疾病捐款倡议书
2014/05/13 职场文书
人力资源职位说明书
2014/07/29 职场文书
十八大标语口号
2014/10/09 职场文书
元宵节寄语大全
2015/02/27 职场文书
Nginx 根据URL带的参数转发的实现
2021/04/01 Servers
Mysql关于数据库是否应该使用外键约束详解说明
2021/10/24 MySQL