Node.js中用Q实现Promise

原文链接:
http://www.ituring.com.cn/article/54547#

还有这篇介绍Promise的,也很屌:
http://www.ituring.com.cn/article/50561#

最近在尝试使用node-mysql,如果一个业务中需要处理多次数据库操作时,写出来的异步嵌套就是噩梦。

搜索了一下,解决方案之一是将业务分解成多个子函数,这样可以有效减少嵌套层数。还有一种解决方案是使用Promises,猛击上面链接查看究竟。

作为学习的成果,以后我也会在这里做一个总结,node-mysql + Q。


updated:

关于Promise

如何理解Promise,本文开头的链接中已经说得很清楚,不用我复述了——实际上我还没能用精炼而精准的语言来描述它。:(

如何创建一个Promise

Q提供了低阶函数q.defer(),这个函数生成的对象的promise属性,即为一个promise。看一下这个例子,如何手工封装一个promise:

function fs_readFile (file, encoding) {
  var deferred = Q.defer()
  fs.readFile(file, encoding, function (err, data) {
    if (err) deferred.reject(err) // rejects the promise with `er` as the reason
    else deferred.resolve(data) // fulfills the promise with `data` as the value
  })
  return deferred.promise // the promise is returned
}
var promise = fs_readFile('myfile.txt')

deferred.reject(err)用于“拒绝”(reject)promise,deferred.resolve(data)用于“完成”(fullfil)promise。
promise被fullfil后,promise.then(fullfil_func, reject_func)中的fullfil处理函数就会被调用;promise被reject后,promise.then(fullfil_func, reject_func)中的reject处理函数就会被调用。

Q为nodejs函数提供了另一个方便版本:q.denodify()。如何记忆这个函数名?de-node-ify,de-node表示“去node化”,即“反node其道而行”,ify是动词化的后缀,连起来就是denodify。于是以上代码等同于:

var fs_readFile = Q.denodify(fs.readFile)
var promise = fs_readFile('myfile.txt')

针对node,Q 还提供了更好用的函数:

var promise = q.nfcall(fs.readFile, 'myfile.txt');//nfcall意思是NodeFunctionCall

怎么样,上面要两行,这里一行就解决了。但要注意的是,nfcall只能用于function,如果要调用某个instance的method呢?用ninvoke():

var conn = ...//获取一个mysql connection
var promise = q.ninvoke(conn, 'query', 'SELECT * FROM table1');

 Q.then()的级联

q.ninvoke(conn, 'query', 'SELECT * FROM table1')
.then(function(result) {
  //do something with result from table1
  return q.ninvoke(conn, 'query', 'SELECT * FROM table2')
    .then(function(result) {
      //do something with result from table2
    });
})
.then(function() {
  //do something2
  //如果这里返回一个promise,则后续then()链将继续等待
  //如果这里返回非promise,则返回的数据直接作为后续then()的fullfil函数的参数
});

以上代码演示了先从table1中取数据,进行一些处理后,再从table2中取数据,进行处理后再走do something2分支。用这种方式写代码,是不是有一种写同步代码的畅快感?

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据