Let me start by saying that I'm very new to Node and possibly made a design error, but I couldn't figure out a better way to do what I want.
I have a function that needs to iterate over an array and for each element in the array it needs to do some async work.
I don't want the caller of the function to proceed until all the elements in the array are processed, so I wrapped my function in a Promise that resolves only when the work on all the elements is finished.
I use eventEmitter inside my function in order to signal when that work on 1 element is finished and now we can start working on the next element.
When all elements are processed array.length==0
and so the promise is resolved.
The problem I'm having is that my event listener is inside the function, and is created each time the function is running. On the other hand, I can't put it outside the function because then I won't be able to resolve the promise for my function.
Can anyone help me figure out how to avoid creating unnecessary listeners and to keep my function working?
I tried using .once()
instead of .on()
when creating the listener. It didn't seem to solve the issue...
function myFunc(objectToTest, testArray) {
return new Promise(function (resolve, reject) {
var array = [];
for (let i = 0 ; i < testArray.length ; i++){
if (objectToTest.name == testArray[i].name){
array.push(testArray[i]);
}
}
eventEmitter.on('done-with-async-work', processArray);
eventEmitter.emit('done-with-async-work')
function processArray() {
if (array.length > 0) {
let itemInArray = array.shift();
// some Async function
auxFunc.asyncFunc(itemInArray).then(function (asyncResult)){
// Triggered when asyncFunc promise is resolved
eventEmitter.emit('done-with-async-work')
}
} else {
console.log("Finished With All Async work!");
resolve("Done with work!")
}
}
});
}
Promise.all, is very usefully if you want to do multiple things at the same time. If you want to do things in a linear way you could chain the promises.
So I could make a snippet, I've just done a pretend async function that sqr's it value, and then I add them all up at the end.
You can do more advanced version too, eg. Bluebird Promises have the map function that has a concurrency option.
var somethings = [12,1,33,23,44,22,11,32,12,44,22,32];
function asyncSqr(v) {
return new Promise(function (resolve, reject) {
setTimeout(function () { resolve(v*v); }, 200);
});
}
function myFunc(a) {
var sum = 0;
return new Promise(function (resolve, reject) {
function doNext() {
var next = a.shift();
if (!next) return resolve(sum);
console.log('sending: ' + next);
return asyncSqr(next).then(function (r) { sum += r; doNext(); });
}
doNext();
});
}
myFunc(somethings).then(function (r) {
console.log('result: ' + r);
});