promise的日常应用

Posted by ngtmuzi on 2015-12-30
班门弄斧

promise在异步处理上真是比原始的回调好了太多,promise大法好~

下面是一些日常工作中总结的各种神秘技巧:(使用bluebird模块)

  • 一般来说都是在request请求或数据库操作之后开始使用promise,当然要直接Promise.resolve()也是可以的

  • mongodb模块原生返回promise对象,真是方便不少,不过它用的是Q模块,没太多精力去了解模块间差异的我会选择在初始连接数据库的时候更换promise库:

    1
    MongoClient.connect(mongoUrl, {promiseLibrary: Promise})
  • mysql方面好像除了sequelize外没什么比较好的promise的模块……因为目前的工作内容都是在mongodb上,对这方面也没做太多了解

  • redis模块中ioredis据说不错,不过也没太多接触

  • 至于网络请求,自然是requestpromise版:request-promise


当以上模块返回了promise对象,就可以用then一路走到黑啦

一般来说我的express路由处理函数都会以这样结尾:

1
2
3
4
function getArticle(req, res, next) {
mongo.article.find(req.query).sort({postTime:-1}).toArray()
.then(res.ok, next);
}

res.ok是自己为了方便而挂上的一个函数,一般类似于

1
res.ok  = res.json.bind(res);

next函数用于将错误传到路由处理函数的末端——错误处理函数,在那里进行统一的错误返回。

后来想想,用next函数统一处理错误固然看来很cooooooool,但也正因为此,对于各种错误的描述无法被带过去——用户并不在意你到底是数据库炸了还是代码写错了,他只想要一个中文的对错误的合理解释,类似“账号密码不正确!”之类的东西,因此考虑了一下,还是改成如下形式:

1
2
3
4
5
6
7
res.ok = function (data) {
res.send(200,data);
};
res.err = _.curry(function (code, err, ext) {
res.status(code || 500);
res.json({msg: err && err.message || err, ext: ext && ext.message || ext});
});

使用了lodash模块将函数柯里化——大概就是这样,虽然不太好说明原理,总之这是一种能让我这样处理回调的一种技术

1
2
sms.csGetStatusReportExEx()
.then(res.ok, res.err(502, '状态报告获取失败'));

真正的错误信息会被带在ext里字段返回,另外res.ok也改成调用适用性更好的res.send函数
(注意这里有个坑,res.send一个数字的话它会以为你只返回一个http状态码,因此虽然res.send(200,data)这种格式已被弃用,但是在目前还是必须这么处理才行)