以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 相关文章推荐
使用javascript访问XML数据的实例
Dec 27 Javascript
Javascript 构造函数详解
Oct 22 Javascript
深入分析JSON编码格式提交表单数据
Jun 25 Javascript
JavaScript拖拽、碰撞、重力及弹性运动实例分析
Jan 08 Javascript
node.js express安装及示例网站搭建方法(分享)
Aug 22 Javascript
深入理解Angularjs向指令传递数据双向绑定机制
Dec 31 Javascript
微信小程序 常用工具类详解及实例
Feb 15 Javascript
JS同步、异步、延迟加载的方法
May 05 Javascript
vue项目环境变量配置的实现方法
Oct 12 Javascript
基于three.js实现的3D粒子动效实例代码
Apr 09 Javascript
Vue的列表之渲染,排序,过滤详解
Feb 24 Vue.js
利用uni-app生成微信小程序的踩坑记录
Apr 05 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安全技术之 实现php基本安全
2010/09/04 PHP
php 实现简单的登录功能示例【基于thinkPHP框架】
2019/12/02 PHP
input的focus方法使用
2010/03/13 Javascript
jquery实现点击文字可编辑并修改保存至数据库
2014/04/15 Javascript
原生javascript实现获取指定元素下所有后代元素的方法
2014/10/28 Javascript
jQuery控制文本框只能输入数字和字母及使用方法
2016/05/26 Javascript
深入理解vue $refs的基本用法
2017/07/13 Javascript
bootstrap模态框嵌套、tabindex属性、去除阴影的示例代码
2017/10/17 Javascript
单页面vue引入百度统计的使用方法示例详解
2018/10/13 Javascript
JavaScript设计模式之享元模式实例详解
2019/01/17 Javascript
vue中组件的3种使用方式详解
2019/03/23 Javascript
简单了解Javscript中兄弟ifream的方法调用
2019/06/17 Javascript
[52:36]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python字符串中查找子串小技巧
2015/04/10 Python
利用Python破解斗地主残局详解
2017/06/30 Python
利用Tkinter(python3.6)实现一个简单计算器
2017/12/21 Python
Python实现简单生成验证码功能【基于random模块】
2018/02/10 Python
对python数据切割归并算法的实例讲解
2018/12/12 Python
python中的单引号双引号区别知识点总结
2019/06/23 Python
python版百度语音识别功能
2019/07/09 Python
Django外键(ForeignKey)操作以及related_name的作用详解
2019/07/29 Python
Python单链表原理与实现方法详解
2020/02/22 Python
打印tensorflow恢复模型中所有变量与操作节点方式
2020/05/26 Python
pandas map(),apply(),applymap()区别解析
2021/02/24 Python
CSS3中设置3D变形的transform-style属性详解
2016/05/23 HTML / CSS
简单几步用纯CSS3实现3D翻转效果
2019/01/17 HTML / CSS
新加坡航空官方网站:Singapore Airlines
2016/10/13 全球购物
荷兰网上鞋店:Ziengs.nl
2017/01/02 全球购物
西班牙多品牌鞋店连锁店:Krack
2018/11/30 全球购物
编写一子程序,将一链表倒序,即使链表表尾变表头,表头变表尾
2016/02/10 面试题
大学生家政服务项目创业计划书
2014/01/30 职场文书
五年后的职业生涯规划
2014/03/04 职场文书
三方合作意向书范本
2015/05/09 职场文书
2015年城管个人工作总结
2015/05/15 职场文书
劳动模范获奖感言
2015/07/31 职场文书
Pytorch 如何实现LSTM时间序列预测
2021/05/17 Python