How to transform Array.forEach to asynchronous with Q.js?
asynchronous, breeze, javascript, q
Solution
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
Problem
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.