Node.js forEach into array

时间:2014-04-11 08:54:12

标签: javascript node.js asynchronous

我正在尝试查询以这种格式返回结果的主服务器:

[
    { ip: '127.0.0.1', port: 28961 },
    { ip: '127.0.0.1', port: 28965 }
]

然后,我需要使用queryDedicated查询每个服务器及其IP,然后在回调中返回数据(与queryMaster相同)。

如果回调中返回的数据有效,它会将其添加到数组中,最后将整个服务器阵列打印到控制台。

var servers = {};

function blabla(host, port) {
    queryMaster(host, port, function(data) {
       async.forEach(data, function(key, next) {
            queryDedicated(key.ip, key.port, function(srv) {
                if (srv) {
                    // if callback data valid, add to array
                    servers[key.ip + ':' + key.port] = srv;
                }
            })

            // valid or not, continue
            next();
        }, function(err) {
            // print servers array
            console.log(servers);
        });
    });
}

问题是我的服务器阵列是空的。

最终'servers'数组应该以这种格式输出数据:

{
    "176.57.141.60:28960": {
        "hostname": "board.landstuhl-atzel.de Schlachthaus #1",
        "address": "176.57.141.60:28960",
        "gametype": "war",
        "mapname": "mp_rundown",
        "players": "0",
        "max_players": "18"
    },
    "176.57.142.144:28663": {
        "hostname": "ClassicSnD.org No mercy for hackers. No lag. No bullshit. [B3]",
        "address": "176.57.142.144:28663",
        "gametype": "sd",
        "mapname": "mp_favela",
        "players": "0",
        "max_players": "18"
    }
}

谢谢!

1 个答案:

答案 0 :(得分:2)

注意:我假设您使用的是async module

使用async

虽然forEach函数可以工作,但我建议尝试使用异步的reduce函数:

  function blabla(host, port) {
    queryMaster(host, port, function(data) {
       async.reduce(data, {}, function(memo, item, next){
          queryDedicated(item.ip, item.port, function(srv) {
            if (srv) {
              memo[item.ip+':'+item.port] = srv;
            }
            // valid or not, continue
            next(null, memo);
          });
     }, function(err, result) {
        // print servers array
        console.log(result);
      });
    });
  }

您可以将备忘录作为空对象传递,而不是拥有全局servers对象:如果您仍然需要全局对象,只需将servers变量作为备忘录传递。

使用vanilla JS的替代解决方案

// simple "parallel" async iterator
function asyncIterator(array, callback, lastCallback){
  var completed = 0;
  array.forEach(function(item){
    callback(item, end);
  });
  function end(){
    completed += 1;
    if(completed >= array.length){
      lastCallback();
    }
  }
}

var servers = {};

function blabla(host, port) {
  queryMaster(host, port, function(data) {
     asyncIterator(data, function(item, next){
       queryDedicated(item.ip, item.port, function(srv) {
          if (srv) {
            servers[item.ip+':'+item.port] = srv;
          }
          // valid or not, continue
          next();
        });
   }, function() {
      // print servers array
      console.log(servers);
    });
  });
}

请注意,这个vanilla解决方案非常简单:迭代器不会考虑输入验证或错误。 如果您打算使用许多async来电,我建议使用上面的库,这将使您的生活更轻松。