You cannot return an asynchronously retrieved result in a synchronous way. So the function main cannot return the results. You should stick to the asynchronous method you have chosen. So with callbacks, you should also provide a callback function when invoking main:
function main(callback){
var all_results = [];
function collect(results) {
all_results.push(results);
// when all 3 calls are complete:
if (all_results.length === 3) callback(all_results);
}
f1(collect);
f2(collect);
f3(collect);
}
Call like this:
main(function (all_results) {
console.log(all_results);
});
As others have stated, promises lead to nicer code in such situations.
How to do it with promises
Let's say you cannot modify functions f1, f2, f3, then you could create promisified versions of them with one simple helper function. Once that is done, the ES6-included method Promise.all will do the rest of the job, so the code becomes quite concise.
Here is a snippet that defines some dummy functions f1, f2, f3 which use setTimeout to get the asynchronous effect:
function promisify(f) {
return new Promise(f);
}
function main(){
return Promise.all([f1, f2, f3].map(promisify));
}
main().then(function (results) {
console.log(results);
});
function f1(callback){
setTimeout(function () {
callback('result from f1');
}, 100);
}
function f2(callback){
setTimeout(function () {
callback('result from f2');
}, 500);
}
function f3(callback){
setTimeout(function () {
callback('result from f3');
}, 200);
}