I need to execute dynamically a function for all items of an array, but Array.forEach
execute in sequence and I need execute in asynchronous.
items.forEach(function(item) {
doSomething(item);
});
I try this:
var promises = [];
items.forEach(function(item) {
var promise = function() {
return Q.fcall(function() {
doSomething(item);
});
};
promises.push(promise());
});
Q.all(promises).then(function () {
otherFunction(datacontext.mainList); //use datacontext.mainList filled.
});
But the execution is always in sequence and I need the execution in parallel.
The doSomething(item)
method:
function doSomething(item) {
var children = getChildren(item); //get data from local with manager.executeQueryLocally
var total = getTotal(children); //simple calculations
datacontext.mainList.push({
name: item.firstName() + ' ' + item.lastName(),
total: total
});
}
Please help me.
I need to execute dynamically a function for all items of an array, but Array.forEach
execute in sequence and I need execute in asynchronous.
items.forEach(function(item) {
doSomething(item);
});
I try this:
var promises = [];
items.forEach(function(item) {
var promise = function() {
return Q.fcall(function() {
doSomething(item);
});
};
promises.push(promise());
});
Q.all(promises).then(function () {
otherFunction(datacontext.mainList); //use datacontext.mainList filled.
});
But the execution is always in sequence and I need the execution in parallel.
The doSomething(item)
method:
function doSomething(item) {
var children = getChildren(item); //get data from local with manager.executeQueryLocally
var total = getTotal(children); //simple calculations
datacontext.mainList.push({
name: item.firstName() + ' ' + item.lastName(),
total: total
});
}
Please help me.
Share Improve this question edited Feb 12, 2014 at 19:47 kuskunko asked Feb 12, 2014 at 14:43 kuskunkokuskunko 3306 silver badges17 bronze badges 6 | Show 1 more comment2 Answers
Reset to default 21This answer assumes that doSomething
is itself an asynchronous operation. This means that it will have to yield to the event loop and wait for another event at least once in a while. If doSomething
is synchronous, there is no benefit to composing it asynchronously.
Within the realm of composite asynchronous jobs, there are serial and parallel variations. The serial model causes job(n + 1) to begin only after job(n) finishes. The parallel model starts all jobs initially and finishes when all jobs are finished. In both of these regards, I can give you tips.
In parallel, you can use Array map and Q.all, assuming doSomething
accepts a value from jobs
and returns a promise:
return Q.all(jobs.map(doSomething))
To do jobs in serial order, use Array reduce.
return jobs.reduce(function (previous, job) {
return previous.then(function () {
return doSomething(job);
});
}, Q());
If you want to perform jobs in serial, but only proceed to the next job depending on the result of the first, you can use reduceRight
to compose a function.
return jobs.reduceRight(function (next, job) {
return function (previous) {
return doSomething(job).then(function (result) {
if (result.isGood(previous)) return result;
return next(result);
});
});
}, function fallthrough(previous) {
throw new Error("No result was satisfactory");
})();
If you have an array that contains functions that need to be executed in order, feeding the output of the previous into the input of the next, you can use reduce
even more succinctly.
return functions.reduce(Q.when, Q());
The tutorial in Q’s readme covers more cases and I am told has been helpful https://github.com/kriskowal/q#tutorial
It appears as though you are executing the promise you are creating immediately during iteration as you push it to the array. Try changing...
promises.push(promise());
To...
promises.push(promise);
var promises = items.map(function() {/*create promise*/ return promise;});
– megawac Commented Feb 12, 2014 at 15:27doSomething
will not be finished in one event. If it does finish in one event, it will always be executed in “serial”, but not necessarily in order. IfdoSomething
returns a promise, or has a callback, and won’t finish in a single event, that opens up the possibility of “parallel”, where multiple jobs will have events that are interleaved. Either way, I can provide tips. – Kris Kowal Commented Feb 12, 2014 at 17:29