0

I am trying to query the master server which returns the result in this format:

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

Then, I need to query every server and it's IP with queryDedicated which then returns the data in a callback (same as queryMaster).

If the returned data in the callback is valid, it will add it to an array, and finally print the whole servers array to the console.

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

The problem is that my servers array is empty.

Final 'servers' array should output the data in this format:

{
    "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"
    }
}

Thanks!

1
  • The problem is that you're calling next() synchronously. You need to go with the async queryDedicated callback! Commented Apr 11, 2014 at 10:41

1 Answer 1

2

Note: I assume that you are using the async module.

With async

While the forEach function can work, I would recommend to try with the reduce function of async:

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

Instead of having a global servers object, you can pass a memo as an empty object: in case you still want the global object, just pass the servers variable as a memo.

Alternative solution with 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);
    });
  });
}

Note that this vanilla solution is pretty simple: the iterator doesn't take in account input validation, or errors. If you are planning to use many async calls I would recommend the library above which will make easier your life.

Sign up to request clarification or add additional context in comments.

5 Comments

console.log(result); returns {} but srv outputs what it should
You're sure that srv is not null in the callback? What if you log it?
I have console.log(srv); right after memo[item.ip+':'+item.port] = srv;
Sure! Sorry, I'll fix it: the callback was returning before the queryDedicated was performed - I guess it is an async call!
Of course there is a solution without it, but I thought you were using it in your code - the async var in you code. Give me a sec to post the alternative.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.