Nodejs,在继续执行之前不等待Redis查询完成

时间:2016-05-05 14:41:14

标签: node.js cassandra redis

使用Node.js我需要通过从Cassandra获取文件路径,使用require()函数动态加载三个文件。从每个文件中我需要获取Redis中的数据并在从Cassandra加载另一个文件之前进行一些验证。这里的问题是:在验证逻辑执行并提供结果之前,下一个文件开始并行加载。验证结果在加载第二个文件之后出现,这不应该发生。第二个文件加载应该等待第一个文件验证逻辑完成,并且只有在验证结果成功时才必须加载。请帮帮我...如何暂停或等待Redis在node.js ???

中完成查询

node.js

"use strict";
var express = require('express');
var cassandra = require('cassandra-driver');
var app = express();
var Promise = require('bluebird');
var redis = Promise.promisifyAll(require('redis'));
var redisClient = redis.createClient(6379, '127.0.0.1');
var client = new cassandra.Client({contactPoints: ['127.0.0.1'], keyspace: 'poc'});
client.execute("SELECT  file FROM testqry1", function (err, result) {
    if (!err){
        if ( result.rows.length > 0 ) {
            for(var i=0; i< result.rows.length; i++){
                var filePath=result.rows[i].get('file');
                var newdat=Promise.promisifyAll(require(filePath));
                var res = newdat(redisClient);
                console.log('res:::'+res);
                if (res=='failed'){
                    return;
                }
            }
        } else {
            console.log("No results");
        }
    }
});

file1.js

var crypto = require('crypto');
var redisValue='';
module.exports = function(redisclient){

redisclient.hmgetAsync("testdata", "text1").then(function(redisValue){
      console.log('value from redis::'+redisValue) 
  }).then(function(){
    var hashedUserID = crypto.createHmac('sha256', 'sample')
                   .update('helloworld')
                   .digest('hex'); 

    function disp(value) {
        console.log('value::'+value);
      }
      disp(hashedUserID);

      console.log('redisValue::'+redisValue);
      if(hashedUserID =='e043e7e68058c8a4cd686db38f01771bd7a04b8bb9a658d3cb40d0be45935094'){
        redata='true';
      }else{
        redata='false';
      }

      console.log('redata::'+redata)
})
}

file2.js&amp; file3.js作为相同的内容

var result1='';
module.exports = function(redisclient){
    redisclient.hmget("testdata", "text1" , function(err, redisValue){  
      console.log('redisValue2 == %s',redisValue);
      if(redisValue == 'test value'){
        result1 = "success";
      }else{
        result1="failed";
      }
    });

    return result1;
} 

输出:

res:::undefined
res:::
res:::
value from redis::test data here
value::e043e7e68058c8a4cd686db38f01771bd7a04b8bb9a658d3cb40d0be45935094
redisValue::
redata::true
redisValue2 == test data here
redisValue3 == hello world test data

1 个答案:

答案 0 :(得分:2)

你说file2 / 3是“相同内容”但它们不在一个关键区域。根据Bluebird的promisifyAll文档(请参阅http://bluebirdjs.com/docs/api/promise.promisifyall.html),此功能会在Redis客户端中为每个核心功能创建...Async版本。您在第一种情况下致电hmgetAsync,但只能在其他人中拨打hmget

这很重要,因为您使用的是异步模式,但具有非异步代码结构。在file2 / 3中,你在异步回调中设置result1,但是在调用可能已经返回之前,在每个调用之后返回它。

您有两种选择:

1:除了redis客户端之外,您还可以通过传递回调将file2 / 3 / etc转换为完全传统的模式:

module.exports = function(redisclient, callback){

然后,您将使用此值调用回调,而不是返回result1

if(redisValue == 'test value'){
    callback(null, "success");
} else {
    callback("failed", null);
}

2:您可以将file2 / 3 / .. N转换为基于Promise的,在这种情况下,您不需要promisifyAll(require(...))它们 - 您可以简单地require()它们。这样的模式可能看起来像:

module.exports = function(redisclient){
    return redisclient.hmgetAsync("testdata", "text1");
};

这是一个更简单,更简洁的选项,如果你继续使用它,你可以看到你甚至可以消除require(),只需使用Cassandra返回的相应数据在file1中执行hmgetAsync。但是,如果不了解您的具体应用需求,很难知道。无论如何,基于Promise的模式通常更短更清晰,但并不总是更好 - 使用它们的性能开销适中。这是你打电话的方式 - 要么会奏效。