以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 相关文章推荐
jQuery LigerUI 使用教程入门篇
Jan 18 Javascript
jquery日历控件实现方法分享
Mar 07 Javascript
JavaScript判断DIV内容是否为空的方法
Jan 29 Javascript
jQuery的实例及必知重要的jQuery选择器详解
May 20 Javascript
JavaScript实现的微信二维码图片生成器的示例
Oct 26 Javascript
基于JS实现限时抢购倒计时间表代码
May 09 Javascript
JavaScript实现一个空中避难的小游戏
Jun 06 Javascript
mongoose更新对象的两种方法示例比较
Dec 19 Javascript
D3.js实现简洁实用的动态仪表盘的示例
Apr 04 Javascript
如何在JavaScript中谨慎使用代码注释
Jun 21 Javascript
EasyUI 数据表格datagrid列自适应内容宽度的实现
Jul 18 Javascript
JSX在render函数中的应用详解
Sep 04 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
Apache下禁止php文件被直接访问的解决方案
2013/04/25 PHP
从零开始学YII2框架(五)快速生成代码工具 Gii 的使用
2014/08/20 PHP
PHP把MSSQL数据导入到MYSQL的方法
2014/12/27 PHP
php中使用url传递数组的方法
2015/02/11 PHP
php获取网站百度快照日期的方法
2015/07/29 PHP
Laravel的throttle中间件失效问题解决方法
2016/10/09 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
2020/02/21 PHP
JQuery判断子iframe何时加载完成解决方案
2013/08/20 Javascript
js判断某个方法是否存在实例代码
2015/01/10 Javascript
JS实现获取剪贴板内容的方法
2016/06/21 Javascript
jQuery插件select2利用ajax高效查询大数据列表(可搜索、可分页)
2017/05/19 jQuery
JavaScript实现提交模式窗口后刷新父窗口数据的方法
2017/06/16 Javascript
react-native ListView下拉刷新上拉加载实现代码
2017/08/03 Javascript
vue 基于element-ui 分页组件封装的实例代码
2018/12/10 Javascript
微信小程序之下拉列表实现方法解析(附完整源码)
2019/08/23 Javascript
Layui点击图片弹框预览的实现方法
2019/09/16 Javascript
vue.js iview打包上线后字体图标不显示解决办法
2020/01/20 Javascript
antd design table更改某行数据的样式操作
2020/10/31 Javascript
[02:06]DOTA2英雄基础教程 暗影萨满
2013/12/16 DOTA
[48:53]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS VG第一场
2014/05/26 DOTA
Python统计列表中的重复项出现的次数的方法
2014/08/18 Python
python根据出生日期获得年龄的方法
2015/03/31 Python
Python编写Windows Service服务程序
2018/01/04 Python
python中的subprocess.Popen()使用详解
2019/12/25 Python
在python3.64中安装pyinstaller库的方法步骤
2020/06/02 Python
python requests库的使用
2021/01/06 Python
python中numpy数组与list相互转换实例方法
2021/01/29 Python
canvas绘制表情包的示例代码
2018/07/09 HTML / CSS
日本最佳原创设计品牌:Felissimo(芬理希梦)
2019/03/19 全球购物
PHP如何自定义函数
2016/09/16 面试题
大学生推广普通话演讲稿
2014/09/21 职场文书
个人贷款收入证明
2014/10/26 职场文书
电影小兵张嘎观后感
2015/06/03 职场文书
用Python爬取英雄联盟的皮肤详细示例
2021/12/06 Python
win10系统xps文件怎么打开?win10打开xps文件的两种操作方法
2022/07/23 数码科技
Go gorilla securecookie库的安装使用详解
2022/08/14 Golang