2016-08-20 92 views
1

我正在学习在nodejs和redis db中开发。我在表达框架。同步调用redis方法

问题:让我们说在redis我有一些关键用户的哈希用户信息:id,比我上次登录的关键user_lastlogged:user_id和比我在user_favourites:user_id他最喜欢的项目。

我想呈现用户详细信息页面,上次登录时间和他的收藏。节点js中的项目。

我会使用这样的东西,但它当然不会工作,因为方法回调是异步运行的。

var redis = require("redis"); 
var client = redis.createClient(); 

router.get('/', function (req, res, next) { 

    var userId='1'; 

    var returnHtml = ''; 

    client.hgetall('user:'+userId, function(err,objects){ 
    returnHtml+=utils.inspect(objects); 
    }); 

    client.hgetall('user_lastlogged:'+userId, function(err,objects){ 
    returnHtml+=utils.inspect(objects); 
    }); 

    client.hgetall('user_favourites:'+userId, function(err,objects){ 
    returnHtml+=utils.inspect(objects); 
    }); 

    res.send(returnHtml); 

}); 

现在请忽略使用适当的redis数据类型等。

这种类型的任务在node.js中是如何解决的?或者,也许在快速js框架(如果有帮助)?

谢谢!

回答

2

声明:我会解决这个承诺更清洁。如果你很好奇,问,我会提供答案。

但是,你问什么,在这里:

router.get('/', function (req, res, next) { 

    var userId='1'; 

    var returnHtml = ''; 

    client.hgetall('user:'+userId, function(err,objects){ 
    returnHtml+=utils.inspect(objects); 
    client.hgetall('user_lastlogged:'+userId, function(err,objects){ 
     returnHtml+=utils.inspect(objects); 
     client.hgetall('user_favourites:'+userId, function(err,objects){ 
      returnHtml+=utils.inspect(objects); 
      res.send(returnHtml); 
     });   
    }); 
    }); 
}); 

更新:蓝鸟答案在另一篇文章中提供。我是问答用户,以便将符合Q这样做:

var q = require('q'); 

var promiseHGetAll = function(key, htmlFragment){ //making a promise version for the function call. 

    if(!htmlFragment) htmlFragment=""; //optional argument, of course 

    var deferred = q.defer(); //a deferred is an object that has a promise in it. and some methods 
    client.hgetall(key,deferred.makeNodeResolver()); 
    //makeNodeResolver is for node methods that have 
    //function(err,result) call back. if the function has an error, 
    //the promise will be rejected and err will be passed to it. 
    // if there is no err, the promise will be resolved and result 
    // will be passed to it. 

    return deferred.promise.then(function(objects){ 
     //the first argument to then() is a function that is called 
     //if the promise succeeds. in this case, this is objects returned 
     // from Redis. 
     return htmlFragment + utils.inpect(objects); 
     // this function can return a promise or a value. 
     // in this case it is returning a value, which will be 
     // received by the next .then() in the chain. 
    }); 
} 

router.get('/', function(req,res){ 
    var userId = "1"; 
    promiseGetAll("user"+userId).then(function(htmlFragment){ 
     //this is called when the promise is resolved, and the 
     //utils.inspect(objects) is called and the return value is 
     //supplied to this then() 
     return promiseGetAll("user_lastlogged"+userId, htmlFragment); 
     //.then() functions can return a promise. in this case, the 
     // next .then will be called when this promise is resolved or rejected. 

    }).then(function(withUserLastLogged){ 

     return promiseGetAll("user_favourites"+userId,withUserLastLogged); 

    }).then(function(returnHTML){ 

     res.send(returnHTML); 

    }).catch(function(error){ 
     //this will be called if there is an error in the node calls, 
     // or any of the previous .then() calls throws an exception, 
     // or returns a rejected promise. it is a sugar syntax for 
     // .then(null, function(err){..}) 
     res.status(503).send(error); 
    }).done(); //throw an error if somehow something was escaped us. shouldn't happen because of catch, but force of habit. 
}) 
+0

是的,谢谢你,如果你想阐述的承诺一点,我会非常感激。 :) –

3

在节点大部分代码是异步的,所以你会碰到这样的情况下,使用了很多。

基本上,你应该使用回调链操作。

var redis = require("redis"); 
var client = redis.createClient(); 

router.get('/', function (req, res, next) { 

    var userId='1'; 

    var returnHtml = ''; 

    client.hgetall('user:'+userId, function(err,objects){ 
    returnHtml+=utils.inspect(objects); 
    client.hgetall('user_lastlogged:'+userId, function(err,objects){ 
     returnHtml+=utils.inspect(objects); 
     client.hgetall('user_favourites:'+userId, function(err,objects){ 
     returnHtml+=utils.inspect(objects); 
     res.send(returnHtml); 
     }); 
    }); 
    }); 
}); 

正如你可以看到它是一个有点回调地狱,你可以看看https://github.com/NodeRedis/node_redis#user-content-promises到promisify来电来使其更具可读性。

随着蓝鸟它可能看起来像:

var bluebird = require('bluebird'); 
var redis = require('redis'); 
bluebird.promisifyAll(redis.RedisClient.prototype); 
bluebird.promisifyAll(redis.Multi.prototype); 

var client = redis.createClient(); 

router.get('/', function (req, res, next) { 

    var userId='1'; 

    var returnHtml = ''; 

    client.hgetallAsync('user:'+userId) 
    .then(function(objects){ 
    returnHtml += utils.inspect(objects); 
    return client.hgetallAsync('user_lastlogged:'+userId); 
    }) 
    .then(function(objects){ 
    returnHtml+=utils.inspect(objects); 
    return client.hgetallAsync('user_favourites:'+userId); 
    }) 
    .then(function(objects){ 
    returnHtml+=utils.inspect(objects); 
    res.send(returnHtml); 
    }) 
    .catch(function(err){ 
    //manage error 
    }); 

}); 
+0

谢谢鲍里斯! –