2016-08-20 84 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

謝謝鮑里斯! –