Well, there are a number of problems with your code, but chief among them is the fact that you cannot save or act upon values you receive inside a callback to anything outside of that callback. Your example has (rewritten for clarity):
var result = []
arry.forEach(function(opt) {
async.call(args, function(err,value) {
result.push(value)
})
})
// result is empty here!
Which cannot work as you expect because you can not know when the inner callbacks complete.
By definition, callbacks are triggered some time in the future, and since you cannot know when, you must do all computation using the result passed to a callback in the callback itself!
Doing otherwise will give you inconsistent results.
UPDATED - Re comment
(Note: hastily typed on iPad during train ride, will fix later if needed.)
The best way would be to use Promises to aggregate the results. Here's a naive example:
/*
* given a value and an optional array (accum),
* pass the value to the async func and add its result to accum
* if accum is not an array, make it one
* return accum
*/
var do_something = (value, accum) => {
// on first pass, accum will be undefined, so make it an array
accum = Array.isArray(accum) ? accum : []
return new Promise((resolve, reject) => {
async_func(value, (err, res) => {
if(err) {
reject(err)
}
accum.append(res)
resolve(accum)
})
})
}
/*
* for each member of input array, apply do_something
* then operate on accumulated result.
*/
Promise.map(input, do_something)
.then(results => {
// results will contain the accumulated results from all
// the mapped operations
})
.catch(err => {
throw err
})
UPDATED - per comment
Using callbacks only, you can achieve the same result using:
const inputs = [...] // array of inputs to pass to async function
const expected_num_of_results = inputs.length
let results = []
const onComplete = (results) => {
// do something with completed results here
console.log(`results: ${results}`);
}
const onResult = (err, res) => { // callback to async_func
if(err) {
throw new Error(`on iteration ${results.length+1}: ${err}`)
}
results.push(res) // save result to accumulator
if( results.length >= expected_num_of_results) { // are we done?
onComplete(results) // process results
}
}
// example async func - REPLACE with actual async function
const async_func = (val,cb) => {
// call callback with no error and supplied value multiplied by 2
cb(null,val*2)
}
// wrapper that takes one value
// and calls async_func with it and predefined callback
const do_async = (value) => {
async_func(value, onResult)
}
// process inputs
inputs.forEach(do_async)
So with:
const inputs = [1,2,3,4,5]
will print:
results: 2,4,6,8,10