2016-09-28 71 views
-1

背景信息节点JS/Express应用程序 - 调用函数中的一个函数

我有一个连接到数据库的Redis查询值的列表中的节点/ Express应用程序。然后对于返回数据中的每个值,我需要进一步查询。

问题

初始查询(Redis的“扫描”命令)工作正常,但如预期的那样HGETALL查询我试图在初步结果集的每个项目不行为。

为了演示这个问题,我在第34行添加了一个console.log命令来打印出当前扫描记录的值......然后在HGETALL的回调函数(第36行)中再次打印出来,但价值是不同的。在我看来,它们应该是一样的......但我确定这是node.js工作方式的基础,我错过了。

代码

27 router.get('/', function(req, res, next) { 
28   redis.send_command("SCAN", [0,"MATCH", "emergency:*"], function(err, reply) { 
29     if (reply) { 
30       var retdata = []; 
31       console.log('length is: ' + reply[1].length); 
32       for (var i = 0; i < reply[1].length; i++) { 
33         var emergIP = reply[1][i]; 
34         console.log('emergIP outside the call: ' + emergIP); 
35         redis.hgetall(emergIP, function (err, data) { 
36           console.log('emergIP inside the call: ' + emergIP); 
37           if (data) {    
38             var temp = emergIP.split(":"); 
39             var key = temp[1]; 
40             console.log('the key is: ' + key); 
41             //retdata.push({key:data.callerid}); 
42           } 
43         }); 
44       }//end for loop 
45       res.send(JSON.stringify(retdata)); 
46     } //end if 
47     else { 
48       //no emergency data defined yet 
49       var retval = {"res":false, "msg":"no emergency data defined"}; 
50       res.send(JSON.stringify(retval)); 
51     
52     }    
53   }); //end send_command 
54 }); 
55 

从代码输出

length is: 8 
emergIP outside the call: emergency:10.1 
emergIP outside the call: emergency:10.2 
emergIP outside the call: emergency:10.13 
emergIP outside the call: emergency:10.14 
emergIP outside the call: emergency:10.18.90 
emergIP outside the call: emergency:10.19 
emergIP outside the call: emergency:10.20 
emergIP outside the call: emergency:10.244 
GET /emergency/ 200 220.368 ms - 2 
emergIP inside the call: emergency:10.244 
the key is: 10.244 
emergIP inside the call: emergency:10.244 
the key is: 10.244 
emergIP inside the call: emergency:10.244 
the key is: 10.244 
emergIP inside the call: emergency:10.244 
the key is: 10.244 
emergIP inside the call: emergency:10.244 
the key is: 10.244 
emergIP inside the call: emergency:10.244 
the key is: 10.244 
emergIP inside the call: emergency:10.244 
the key is: 10.244 
emergIP inside the call: emergency:10.244 
the key is: 10.244 

问题

我认为问题是,我期待在send_command功能回调顺序发生。换句话说,也许问题是我不应该在另一个函数调用中进行函数调用? 这是我的第一个节点应用程序...我正在学习。

任何建议,将不胜感激。

+0

您的帖子是重复的http://stackoverflow.com/questions/9644197/sequential-execution-in-node-js – amitmah

+0

@amitmah,是的,我认为你是对的。但我想我不知道找到合适的术语来寻找这篇文章。我想知道我是否应该把我的问题留给那些可能用我的方式来表达他们问题的人......? – Happydevdays

回答

0

除了使用async.forEach你可以利用关闭,并立即调用的函数:

// get all elements from redis 
function getAll(emergIP, callback) { 
    redis.hgetall(emergIP, function (err, data) { 
    if (err) { 
     return callback(err); 
    } 

    console.log('emergIP inside the call: ' + emergIP); 
    if (data) { 
     var temp = emergIP.split(":"); 
     var key = temp[1]; 
     console.log('the key is: ' + key); 
    } 

    return callback(null, data); 
    }); 
} 

// Iterate all over the results 
function getResults (reply, callback) { 
    var retdata = []; 
    console.log('length is: ' + reply.length); 
    var length = reply.length; 

    if (!length) { 
    return callback(null, retdata); 
    } 

    for (var i = 0; i < length; i++) { 
    var emergIP = [i]; 
    console.log('emergIP outside the call: ' + emergIP); 

    (function (emergIP, i) { 
     getAll(emergIP, function (err, data) { 
     if (err) { 
      // @todo: how would you like to handle the error? 
     } 

     retdata.push({key:data.callerid}); 

     if (i === length - 1) { 
      return callback(null, retdata); 
     } 
     }); 
    }(emergIP, i)); 
    } //end for loop 
} 

router.get('/', function (req, res, next) { 
    redis.send_command("SCAN", [0, "MATCH", "emergency:*"], function (err, reply) { 
    if (reply) { 
     getResults(reply[1], function (err, data) { 
     if (err) { 
      // @todo: how would you like to handle this in case of error? 
     } 

     res.send(JSON.stringify(data)); 
     }); 
    } //end if 
    else { 
     //no emergency data defined yet 
     var retval = { "res": false, "msg": "no emergency data defined" }; 
     res.send(JSON.stringify(retval)); 

    } 
    }); //end send_command 
}); 

编辑

我修改了一下代码返回当迭代完成时json。这不是完美的代码,因为在这种情况下,如果没有迭代结果,它将根本不会返回客户端的响应。考虑使用async.each:http://caolan.github.io/async/docs.html#.each

EDIT2

我试着去耦代码,并将其分成功能。您可以将这些功能移到另一个文件,然后将它们请求到路由器中。很抱歉,如果有任何不允许代码正常运行的错字,我实际上并没有尝试运行它。

+0

这工作完美。我将研究节点关闭和立即调用的函数以供将来参考。非常感谢 – Happydevdays

+0

唯一的其他相关问题是,我应该如何/在哪里通过响应对象返回这些数据以便在网页上显示?我试图取消注释retdata.push()方法,但它不起作用 – Happydevdays

+0

当然,它不会工作,因为记住,在迭代内执行异步代码:)所以,您的代码将发送回客户端的响应' res.send(JSON.stringify(retdata));'不等待redis.hgetall完成。我会稍后发布一个解决方案作为另一个答案。 –

相关问题