when 让你跳出异步回调噩梦 node.js下promise/A规范的使用
其实关于promise 的博客,前端时间专门写了一篇关于 promise 规范的文章,promise规范 让 javascript 中的异步调用更加人性化.
简单回忆下:
promise/A规范定义的“Deferred/Promise”模型
其实是实现了“发布/订阅”模型.
通过Deferred对象发布事件,
包括下面2种事件
完成 --> resolve事件,
失败 --> reject事件,
通过Promise对象进行对应完成或失败的订阅
类似于任务状态转变时事件被触发.
将会对应的执行事件绑定函数.
每个Promise任务都有三种状态:
默认(pending)、完成(fulfilled)、失败(rejected)
1.默认状态可以单向转移到完成状态,这个过程叫resolve,对应的方法是deferred.resolve(Value);
2.默认状态还可以单向转移到失败状态,这个过程叫reject,对应的方法是deferred.reject(reason);
3.默认状态时,还可以通过deferred.notify(message)来宣告任务执行信息,如执行进度;
4.状态的转移是一次性的,一旦任务由初始的pending转为其他状态,就会进入到下一个任务的执行过程中。
今天其实是想和大家分享下 when 这个 npm 包,或许未来不久你将会用到.
github地址: https://github.com/cujojs/when
我们通过一个具体的模拟示例来学习 when
应用场景:
假如我有一个服务,每天定时运行.
做什么任务呢,就是去证券/银行站点读取当天的汇率信息,然后保存到自己的数据库.
逻辑很简单:
查看当天是否有最新汇率信息
如果有,获取汇率信息
如果获取到,保存到本地数据库
我们依次来定义3个方法:
//获取汇率信息
function get(callback){
//具体请求url,分析dom全部省略,全当调用了下面的一个黑盒方法来实现
yijiebuyi_util.getHtml('http://aaa.com/bbb',function(err,info){
callback(err,info);
});
}
//保存汇率信息
function save(info,callback){
//写入数据库方法忽略
yijiebuyi_util.save(info,function(err,result){
callback(err,result);
});
}
OK,我们先来一把普通调用方法
function main(callback){
//获取汇率信息
get(function(err,info){
if(err){
return callback(err,null);
}
//保存汇率信息
save(info,function(err,result){
if(err){
return callback(err,null);
}
//回调保存状态
callback(null,result);
});
});
};
如果业务更复杂的话,一层嵌套一层,看上去是不很带劲
等到维护的时候可能就费劲了.
有人说要使用 async 来控制,确实可行,而且我们一般也就是这样处理的.
async 可以把整个流程控制住,比如串联执行,下一步执行函数使用上一步执行结果等.
但是今天我们推荐大家一种看上去很优雅的解决方案.
我们从处理流程跳出来,不要在流程上去控制业务,而是从每一个业务方法入手,让方法通过 when 构建一个promise规范的方法.
我们还是要把上面的方法全部修改一下:
首先安装,应用 when
npm install -g when
var when=require('when');
function get(){
var deferred = when.defer();
yijiebuyi_util.getHtml('http://aaa.com/bbb',function(err,info){
if(err)
deferred.reject(err);
else
deferred.resolve(info);
return deferred.promise;
});
}
function save(info,callback){
var deferred = when.defer();
yijiebuyi_util.save(info,function(err,result){
if(err)
deferred.reject(err);
else
deferred.resolve(result);
return deferred.promise;
});
}
上面2个方法我们已经改装完毕,下面看看 main 方法中如何调用呢.
function main(){
get().then(save).catch(function(err){
console.log(err);
});
}
我们并没有在流程上控制业务逻辑处理顺序.而是像同步代码一样按照执行顺序调用即可,是不是很美好.
then方法包括三个参数,
onFulfilled、
onRejected、
onProgress
promise.then(onFulfilled, onRejected, onProgress)
从参数名你就可以发现这几个方法应该是事件处理函数.
这也应了我们上面所说的, promise 本身就是一种事件发布/订阅模型.
所以上面 then 里的三个函数相当于事件绑定函数.(就是观察者)
当上一个任务被deferred.resolve(data) ,对应在本任务就会触发 onFulfilled 方法.
当上一个任务被 deferred.reject(err) ,对应的本任务就会触发 onRejected 方法.
任何一个任务, onFulfilled 或 onRejected 方法只能被触发一个,并且触发一次.
我们上面main 方法中最后的 catch(function(err){.....}) 是怎么回事.
when 提供了极其简单的传递错误机制,多个任务执行时,我们可以在最后一个任务定义onRejected
或者在 then 调用的最后用 catch 来捕捉错误.
***end***
when 让你跳出异步回调噩梦 node.js下promise/A规范的使用的更多相关文章
- 深入浅出Node.js(下)
(五):Node.js的异步实现 专栏的第五篇文章<Node.js的异步实现>.之前介绍了Node.js的事件机制,也许读者对此尚会觉得意犹未尽,因为仅仅只是简单的事件机制,并不能道尽No ...
- node.js 下依赖Express 实现post 4种方式提交参数
上面这个图好有意思啊,哈哈, v8威武啊.... 在2014年的最后一天和大家分享关于node.js 如何提交4种格式的post数据. 上上一篇说到了关于http协议里定义的4种常见数据的post方法 ...
- npm 是node.js下带的一个包管理工具
npm 是node.js下带的一个包管理工具 npm install -g webpack webpack是一个打包工具 gulp是一个基于流的构建工具,相对其他构件工具来说,更简洁 ...
- node.js下操作cookie
cookie,又是cookie.工作中与cookie打交道很多次,不过时间跨度也大,每总结多一次,就加深了解多一点. cookie,一定是放在浏览器中的,用于浏览器保存一些小额度的内容.每次我们去访问 ...
- Node.js之Promise维护(同步)多个回调(异步)状态
金天:学习一个新东西,就要持有拥抱的心态,如果固守在自己先前的概念体系,就会有举步维艰的感觉..NET程序员初用node.js最需要适应的就是异步开发, 全是异步,常规逻辑下遍历列表都是异步,如何保证 ...
- 避免多层回调,Node.js异步库Async使用(series)
未使用Async之前coffeescript写的代码: exports.product_file_add = (req,res) -> if !req.param('file_id') retu ...
- node.js的Promise库-bluebird示例
前两天公司一哥们写了一段node.js代码发给我,后面特意提了一句“写的不太优雅”.我知道,他意思是回调嵌套回调,因为当时比较急也就没有再纠结.然而内心中总记得要解决这个问题.解决node.js的回调 ...
- Node.js下的Hello World
Node.js技术现在可谓是如火如荼,前后端都统一为Javascript的体验绝对是受到了很多人的青睐,我都后悔以前没抽时间好好学一学Javascript了. 首先,我来介绍一下Node.js.本人实 ...
- 在Node.js使用Promise的方式操作Mysql
最近在学习Node.js,虽然早就听说了回调地狱结果过了一周就遇到了.所以花时间学习了了一下Promise.虽然还有Async/await.co.生成器等选择,但是因为本人基础较差,以及时间问题所以决 ...
随机推荐
- Day03 知识点
一.单行注释与多行注释 # 用来标记不运行的程序 pycharm 快捷键 ctrl+/ 可以在程序上方 也可以在程序后面 (PEP8) 多行注释 用三引号,一般推荐三双引号来做注释. 二.数据类型 ( ...
- 【ACM】N皇后问题
N皇后问题 #include <iostream> #include <cmath> using namespace std; ; //判断当前位置的皇后加入是否成立 bool ...
- hadoop单机配置
条件: 先下载VMware1.2,然后安装. 下载ubuntu-1.4.05-desktop-amd64.iso.下载地址:http://mirrors.aliyun.com/ubuntu-relea ...
- wampserver启动时图标不变绿的解决方法
有2种可能: 1.你安装wamp的时候安装路径中有中文,把路径全部改为英文. 2.其他软件占用了80端口号,解决方法是在服务中找微软的sql server或者其他服务,关掉服务后重启就行了.
- 修改model,映射到表中
1. 当使用EF code first创建数据表后,数据库中会自动创建一个名为:dbo.__MigrationHistory的系统数据表, 如果尚未启用数据库迁移功能,那么每次在应用程序运行时,都会对 ...
- intellijidea课程 intellijidea神器使用技巧 6-1 Spring的关联
待学完spring之后再来看 Spring的关联位置:菜单->File->Project Structure->Facets功能:帮助管理Spring容器.还提供了很多其他的管理,比 ...
- 解决jQuery在chrome中获取height为0
笔者之前在一家创业公司做过项目,当时遇到这么一个奇怪的问题,我需要用一个jQuery的height()方法获取一个div的高度,但是在chrome浏览器上面有时可以正常获取,但是同一个页面刷新多几次获 ...
- ArrayList、Vector、HashMap、HashSet
1. list 和 set 的有序无序是否可重复 List是有序可重复的: Set是无序不可重复的: 2.ArrayList.Vector.HashMap.HashSet的默认初始容量.加载因子.扩 ...
- XHML教会我的一些东西-3
在寒假期间,隔几天就同学聚会,每天都是起床困难户.每天都想着要完成任务,要学习新的东西.但是总是被自己惰性占为上风.感觉自己很没用,但是又继续堕落.真的不能理解自己.呵呵.... 在放假一段时间之后, ...
- 云集微助手安装教程和授权说明old
安装教程 一 .手机越狱(如果已经越狱请跳过此步,直接进行第二步) 越狱教程:http://jailbreak.25pp.com/yueyu/ 二 .安装触动精灵(如果你已安装触动精灵最新版请跳过此步 ...