从异步回调函数将对象推送到本地数组

Posted

技术标签:

【中文标题】从异步回调函数将对象推送到本地数组【英文标题】:Push object into local array from asynchronous callback function 【发布时间】:2014-08-12 01:16:46 【问题描述】:

我在我的服务器上使用 node.js,并使用 redis 密钥库来存储有关我的角色的数据。每个连接都有它自己的特点。我想将所有关于字符的数据(人,有它的名字,年龄,职业,......)到 Characters 数组中,这样我就可以有选择地将它发送到连接的客户端。

var Characters = [];
for (var ID in Connections) 
    redis_client.HGETALL(ID, function(err, result) 
        if (result) 
            Characters.push(result);
        
    );

console.log(Characters);

我读过,这是由于异步与同步的问题,所以我做了全局变量字符。

//global variables
var character;
//function code
var Characters = [];
for (var ID in Connections) 
    redis_client.HGETALL(ID, function(err, result) 
        character = result;
    );
    if(character) 
         console.log(character); // returns correct result
         // make copy of character
        Characters.push(JSON.parse(JSON.stringify(character)));
        character = undefined;
    

console.log(Characters); // array of 1 character * number of connection
                                                    //BUT I expect different character for each connection

【问题讨论】:

【参考方案1】:

有不同的方法,

最简单的方法是创建一个又一个调用异步函数,如下

    var Characters = [];
    var objectKeys = Object.keys(Connections);
    var ID = 0; 
    if (ID < objectKeys.length) 
        doCall(objectKeys[ID]);
    else 
        console.log(Characters);
   function doCall(key) 

        redis_client.HGETALL(key, function(err, result) 
            if (result) 
                Characters.push(result);
            
            ID++;
            if ( ID < objectKeys.length)
               doCall(objectKeys[ID]);
            else 
               console.log(Characters);
        );
   

【讨论】:

嗨,你能解释一下为什么如果我替换 console.log(Characters);在从第 3 行开始的第 3 行,用 for (var ID in Connections) Connections[ID].emit("snapshot", MyIndex: Indices[ID], Characters: Characters ); (它的 socketio 发送函数)然后是整个代码不起作用(即使在 ID++ 所在的行上; - ID 未定义并变成 NaN。但是:如果我将这个 for 循环放入另一个函数中并且只调用此函数而不是 console.log(Characters); 代码作为预计?【参考方案2】:

当您有异步调用和全局变量时,常规 for 循环无法正常工作。这是一个可以工作的循环版本(确保安装了异步。如果没有,请执行“npm install async”):

var async = require('async');   
var Characters = [];

async.each(Connections, function(ID, callback) 
  redis_client.HGETALL(ID, function(err, result) 
    if (result) 
        Characters.push(result);
    
    callback(null);
  );
, function(err)  // this function gets called when the loop is done
  console.log("finish:");
   // print out your array
  for (var i = 0, len = Characters.length; i < len; i++) 
    console.log(Characters[i]);
  
);

【讨论】:

async.each 不会通过 Connection 数组进行交互。我有: for (ID in Connections) console.log(ID); 这会打印 Connections 中对象的键。在这个命令下我有 async.each(Connections, ... 但它不会做任何操作,即使之前的“for”打印了一些键,它只会打印“finish”。 async.each() 应该。你在答案中调用了回调(null)吗?没有它, async.each() 将不会继续处理数组中的下一项 这是我运行的示例,它按预期工作,只是没有使用 HGETALL(): var async = require('async'); var 字符 = []; var Connections = [1, 2, 3]; async.each(Connections, function(ID, callback) Characters.push(ID); callback(null); , function(err) console.log("finish: %d", Characters.length); for ( var i = 0, len = Characters.length; i

以上是关于从异步回调函数将对象推送到本地数组的主要内容,如果未能解决你的问题,请参考以下文章

无法弄清楚如何将数据异步推送到数组

promise

nodejs异步回调函数中this问题,求助

如何在没有回调地狱的情况下加载图像?

Array.map() 的异步回调

sequelize.transaction() 可以将异步函数作为回调吗?