利用promise写出更加优美的nodejs程序
2015-08-12 13:36
776 查看
http://my.oschina.net/sundq/blog/227410
摘要 nodejs所有的操作都是异步和callback模式,这样做的坏处是很容易造成或掉函数调用大坑,本文介绍如何使用promise写出更简洁明了的程序。
nodejs promise callback hell
目录[-]
什么是promise
将一般的异步调用的函数转换为promise风格的函数
使用方法
比如一般情况下,我们异步读取文件会写出下面的代码:
我们可以把
这样我们就可以这样调用这个方法了:
可以看到这样调用更加直接明了。
各个回调函数顺序传递数据:
在
可以很轻松的在回调函数之间传递参数,看下面的例子:
可以看到
收集各个回调函数产生的数据:有时候我们需要执行很多回调函数,然手把这个回调函数的数据一齐传递给一个函数处理,此时我们可以使用
统一处理错误:传统的回调函数方式使用的话,我们需要在每一个回调函数里判断是否有错误需要处理,这样会存在很多冗余代码,使用
摘要 nodejs所有的操作都是异步和callback模式,这样做的坏处是很容易造成或掉函数调用大坑,本文介绍如何使用promise写出更简洁明了的程序。
nodejs promise callback hell
目录[-]
什么是promise
将一般的异步调用的函数转换为promise风格的函数
使用方法
什么是promise
promise一个标准,它描述了异步调用的返回结果,包括正确返回结果和错误处理。关于详细的说明文档可以参考Promises/A+。目前实现
promise标准的模块有很多,如Q、]bluebird和]Deferred,下面我们以Q为例,介绍一下
promise在
nodejs中的使用方法。
将一般的异步调用的函数转换为promise
风格的函数
比如一般情况下,我们异步读取文件会写出下面的代码:fs.readFile("test.txt",function(err,data){ if(!err){ console.log(data); }else{ console.error(err); } });
我们可以把
fs.readFile函数封装为
promise风格的函数,如下:
var preadFile = function(file){ fs.readFile(file,function(err,data){ var deferred = Q.defer(); if(!err){ deferred.resolve(data); }else{ deferred.reject(err); } return deferred.promise; }); }
这样我们就可以这样调用这个方法了:
//then 的第一个参数是正确处理函数,第二个参数是错误处理函数 preadFile("test.txt").then(console.log,console.error);
可以看到这样调用更加直接明了。
使用方法
各个回调函数顺序传递数据:在
nodejs中我们回去数据时,时常遇回调函数的返回结果需要传递给下一个回调函数,到时很大的回调函数嵌套,
promise
可以很轻松的在回调函数之间传递参数,看下面的例子:
var fun1 = function (data,cb) { cb(null,data+" fun1"); } var fun2 = function (data,cb) { cb(null,data+" fun2"); } var fun3 = function (data,cb) { cb(null,data+" fun3"); } function main(data,cb){ fun1(data,function(err,data){ if(!err){ fun2(data,function(err,data){ if(!err){ fun3(data,cb); }else{ cb(err); } }); }else{ cb(err); } }); }
可以看到
main函数为了得到数据,需要嵌套调用
fun1,
fun2和
fun3,如果需要调用很多函数,那么会形成很大的回调函数嵌套调用,导致代码看起来很丑陋,而且不容易维护,下面我们改用
promise重写这段代码:
var Q = require("q"); var fun1 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun1"); return deferred.promise; } var fun2 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun2"); return deferred.promise; } var fun3 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun3"); return deferred.promise; } function main(data,cb){ fun2("test") .then(fun3) .then(fun4) .done(function(data){ cb(null,data);//ok 获得的最终数据为 --->"test fun1 fun2 fun3" },function(err){ cb(err);//failed }); }
收集各个回调函数产生的数据:有时候我们需要执行很多回调函数,然手把这个回调函数的数据一齐传递给一个函数处理,此时我们可以使用
all和
spread方法,参看如下代码:
var Q = require("q"); var fun1 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun1"); return deferred.promise; } var fun2 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun2"); return deferred.promise; } var fun3 = function (data) { var deferred = Q.defer(); deferred.resolve(data+" fun3"); return deferred.promise; } Q.all([ fun2("test1"),fun3("test2"),fun4("test3") ]).spread(function(){ console.log(arguments);//获得的参数为('test1 fun1', 'test2 fun2', 'test3 fun3' ) });
统一处理错误:传统的回调函数方式使用的话,我们需要在每一个回调函数里判断是否有错误需要处理,这样会存在很多冗余代码,使用
promise的话,可以使用
done或者
fail统一在一个函数中处理错误,如第一个例子一样,使用
done方法的第二个参数处理错误。
相关文章推荐
- 在 Node.js 中用 Q 实现 Promise – Callback 之外的另一种选择
- NodeJs教程
- Node.js async in practice: When to use what?
- 在Node.js中使用promise摆脱回调金字塔
- Node.js 常见面试题
- Leetcode#19||Remove Nth Node From End of List
- node.js--Less
- [转]Nodejs开发框架Express4.x开发手记
- LeetCode题解:Delete Node in a Linked List
- Remove Nth Node From End of List
- HtmlParser初探--使用Nodefilter和Visitor进行网页分析
- [LeetCode] Count Complete Tree Nodes
- [leetcode-116]Populating Next Right Pointers in Each Node(c++)
- cassandra nodejs driver maillist link
- Node.js详细解析
- 【LeetCode-面试算法经典-Java实现】【116-Populating Next Right Pointers in Each Node(二叉树链接右指针)】
- 我用的一些Node.js开发工具、开发包、框架等总结
- HDU 4587 TWO NODES 枚举+割点
- HDFS源码分析(一)-----INode文件节点
- NodeJS下的阿里云企业邮箱邮件发送问题