【问题标题】:Nodejs, not waiting for Redis query to complete before continuing with executionNodejs,在继续执行之前不等待 Redis 查询完成
【发布时间】:2016-08-31 09:52:56
【问题描述】:

使用 Node.js,我需要使用 require() 函数通过从 Cassandra 获取文件路径来动态加载三个文件。我需要从每个文件中获取 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 & 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

【问题讨论】:

    标签: node.js cassandra redis


    【解决方案1】:

    您说 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 的模式通常更短、更简洁,但并不总是更好——使用它们会有适度的性能开销。走哪条路是你的决定 - 两者都行。

    【讨论】:

    • 我尝试了这两种选择,对于回调方法,我得到“回调不是函数”,对于 promise 方法,我得到 {"isFulfilled":false,"isRejected":false}' 结果。
    • 我的回答被改写了。我在第一个块中引用了一个常见的 NodeJS 回调术语 cb,在第二个块中引用了 callback。他们显然需要匹配。我已对其进行了更新以反映这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多