同步调用redis方法

我正在学习在nodejs和redis db中开发。 我在expression框架。

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

我想呈现用户的详细信息页面,最后login时间和他的collections。 项目在节点js。

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

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数据types等。

这种任务在node.js中通常如何解决? 或者也许在快速JS框架(如果有帮助)?

谢谢!

在节点中大部分代码是asynchronous的,所以你会遇到这个用例很多。

基本上,你应该使用callback连锁操作。

 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); }); }); }); }); 

正如你可以看到这是一个callback地狱,你可以看看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 }); }); 

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

但是,对于你所问的,在这里:

 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. })