如何使用deferrable执行一系列Redis操作?

时间:2013-10-11 15:30:43

标签: javascript node.js redis promise

我有以下操作来创建具有node_redis的用户:

server.post('/create_user', function(req, res, next) {
  console.log(req.body);
  var body = req.body;
  client.hincrby('users', 'count', 1, function(err, id) {
    client.hmset('user:'+id, 
    'username', body.username, 
    'password', body.password, 
    'email', body.email, function(err, write) { 
      client.hmget('user:'+id, 'username', 'email', function(err, read) {
        res.send({id: id, username: read[0], email: read[1]});
      });
    });
  });
})

我在考虑阅读Deferrable和Promisses:http://blog.jcoglan.com/2011/03/11/promises-are-the-monad-of-asynchronous-programming/

如何使用Deferrables和Promisses重写此代码,允许更清晰的异常处理以及更好的过程维护?

行动基本上是:

  1. 增加计数器以获取ID
  2. 设置ID为
  3. 的用户的Redis哈希值
  4. 从Redis返回创建的用户

2 个答案:

答案 0 :(得分:3)

你可以做承诺:

var Promise = require("bluebird");
//assume client is a redisClient
Promise.promisifyAll(client);

server.post('/create_user', function(req, res, next) {
    console.log(req.body);
    var body = req.body;
    client.hincrbyAsync('users', 'count', 1).then(function(id){
        return client.hmsetAsync(
            'user:' + id,
            'username', body.username,
            'password', body.password,
            'email', body.email
        );
    }).then(function(write){
        return client.hmgetAsync('user:'+id, 'username', 'email');
    }).then(function(read) {
        res.send({id: id, username: read[0], email: read[1]});
    }).catch(function(err){
        res.writeHead(500);
        res.end();
        console.log(err);
    });
});

这不仅比瀑布更好,但如果你有同步异常,你的过程不会崩溃,甚至是同步 例外被转变为承诺拒绝。虽然我很确定上面的代码不会抛出任何这样的例外: - )

答案 1 :(得分:1)

我已成为异步库的粉丝。它非常高效,并且具有清理可读性的出色方法。

以下是使用async瀑布函数重写的示例。

瀑布的基本设置是:

async.waterfal([函数数组],finalFunction);

注意:瀑布方法期望回调函数始终将第一个参数作为错误。关于这一点的好处是,如果在任何步骤中返回错误,它将直接转到带有错误的完成函数。

var async = require('async');

server.post('/create_user', function(req, res, next) {
  console.log(req.body);
  var body = req.body,
      userId;

  async.waterfall([
    function(cb) {
      // Incriment
      client.hincrby('users', 'count', 1, cb);
    },
    function(id, cb) {
      // Higher Scope a userId variable for access later.
      userId = id;
      // Set
      client.hmset('user:'+id, 
        'username', body.username, 
        'password', body.password, 
        'email', body.email, 
        cb);
    },
    function(write, cb) {
      // Get call.
      client.hmget('user:'+userId, 'username', 'email', cb);
    }
  ], function(err,read){
      if (err) {
        // If using express:
        res.render('500', { error: err });
        // else
        res.writeHead(500);
        res.end();
        console.log(err);
        return;
      }
      res.send({id: userId, username: read[0], email: read[1]});
  })
})