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 Answer 1
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.
5 Comments
srv is not null in the callback? What if you log it?queryDedicated was performed - I guess it is an async call!async var in you code. Give me a sec to post the alternative.
next()synchronously. You need to go with the asyncqueryDedicatedcallback!