Nodejs,在继续执行之前不等待Redis查询完成 [英] Nodejs, not waiting for Redis query to complete before continuing with execution

查看:1159
本文介绍了Nodejs,在继续执行之前不等待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 var filePath = result.rows [i] .get('file');
var newdat = Promise。 promisifyAll(require(filePath));
var res = newdat(redisClient);
console.log('res :::'+ res);
if(res ==' ){
return;
}
}
} else {
console.log(No results);
}
} b $ b});



  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 ')
.digest('hex');

函数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& file3.js as same content

  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 :::
来自redis :: test data的值
value :: e043e7e68058c8a4cd686db38f01771bd7a04b8bb9a658d3cb40d0be45935094
redisValue ::
redata :: true
redisValue2 ==这里的测试数据
redisValue3 == hello world test data


解决方案

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



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



你有两个选择:



1:你可以通过传递一个回调函数将file2 / 3 / client:

  module.exports = function(redisclient,callback){
pre>

而不是返回 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的模式通常要短得多,更干净,但并不总是更好 - 使用它们会产生中等的性能开销。这是你的电话,你走什么 - 或者将工作。


Using Node.js I need to load three files dynamically with a require() function by fetching the file path from Cassandra. From each file I need to fetch data that is in Redis and do some validation before loading another file from Cassandra. The issue here is: before the validation logic executes and provides results the next file's start to get loaded in parallel. The validation result comes after the loading of the second file, which shouldn't happen. The second file loading should wait for the first file validation logic to be complete and must load only if the validation result is a success. Please help me ... How do I pause or wait for Redis to complete the query in 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 & file3.js as same content

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

Output :

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

解决方案

You say that file2/3 are "same content" but they aren't in one critical area. Per Bluebird's documentation for promisifyAll (see http://bluebirdjs.com/docs/api/promise.promisifyall.html), this feature creates an ...Async version of each core function in the Redis client. You call hmgetAsync in your first case, but you only call hmget in your others.

This is important because you're using an async pattern but with a non-async code structure. In file2/3 you set result1 inside an async callback, but then return it below each call before the call could possibly have returned.

You have two choices:

1: You can convert file2/3/etc to a fully traditional pattern by passing in a callback in addition to the redis client:

module.exports = function(redisclient, callback){

Instead of returning result1, you would then call the callback with this value:

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

2: You could convert file2/3/..N to be Promise-based, in which case you do not need to promisifyAll(require(...)) them - you can simply require() them. Such a pattern might look like:

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

This is a much simpler and cleaner option, and if you keep going with it you can see that you could probably even eliminate the require() and simply do the hmgetAsync in file1 with appropriate data returned by Cassandra. But it's hard to know without seeing your specific application needs. In any event, Promise-based patterns are generally much shorter and cleaner, but not always better - there IS a moderate performance overhead for using them. It's your call which way you go - either will work.

这篇关于Nodejs,在继续执行之前不等待Redis查询完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆