Monday, May 20, 2024
69
rated 0 times [  70] [ 1]  / answers: 1 / hits: 6842  / 11 Years ago, wed, february 12, 2014, 12:00:00

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.


More From » asynchronous

 Answers
3

This 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


[#47804] Tuesday, February 11, 2014, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
makaylahk

Total Points: 166
Total Questions: 94
Total Answers: 117

Location: Gabon
Member since Sat, Jul 25, 2020
4 Years ago
;