Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript loop promises iterating with array in arguments

I am trying to loop through an array of AsynWork to be done. And cant flood the system with async work done all at the time. so I am trying to do one by one with promises. My problem is that I need to go though an array of values so each async works on each value of the array. I managed to do it with this code, but it works for my specific case. Can't make it general. What would be the approach to make it reusable for other type of arrays? I have seen some solutions with array.reduce then promises but cant figure it out. Also have seen examples with Q but not using, if it can be done with simple javascript would be better.

My Code:

function doSomething(ObjIn1, ObjIn2) {
    return new Promise(function(resolve, reject) {
        console.log("doSomething: ObjIn1: " + ObjIn1 + "  ObjIn2: " + ObjIn2);
        setTimeout(function() {
            console.log("doSomething Done: ObjIn1: " + ObjIn1 + "  ObjIn2: " + ObjIn2);
            resolve(ObjIn1, ObjIn2);
        }, 500);
    })
}

function LoopPromises(Function2Loop, functionOptions, Counter, Max) {
    console.log("Counter: " + Counter);
    if (Counter < Max) {
        Function2Loop.apply(this, [functionOptions[0][Counter], functionOptions[1]]).then(function() {
            Counter++;
            LoopPromises(Function2Loop, functionOptions, Counter, Max);
        });
    }
}

LoopPromises(doSomething, [
    ["A1", "A2", "A3"], "ARG2TESTE"
], 0, 3)
like image 848
Jose Neto Avatar asked Jan 02 '26 05:01

Jose Neto


1 Answers

You're overthinking this :) A function with arguments is the same as a function without arguments closing over a function with arguments so:

a(1,2,3,4);

Is the same as

(() => a(1,2,3,4))(); 

Except perhaps negligibly slower. I'm assuming you need to queue the work for an arbitrary amount of promises. If you need to do it for a fixed number - you can just then between them. Let's see how we can do this:

// runs fn on the array elements in sequence, but 
function sequence(fns) { // fns - functions returning promises
    return fns.reduce((prev, nextFn) => { // 'fold' the array
        return prev.then(nextFn); // after the previous is done, execute the next
    }, Promise.resolve()); // start with an empty promise
}

Make sure you understand reduce first. For convenience - let's see an example without it:

function sequence(fns) { // fns - functions returning promises
    var queue = Promise.resolve();
    fns.forEach(fn => queue = queue.then(fn));
    return queue;
}

We're iterating through our array of work (functions) and executing them one after the other where we execute the next after the promise the previous returned resolved.

Where the values wait for each other based on the promise resolving (via then). This would let you do:

sequence([
   () => new Promise(r => setTimeout(r, 500));
   () => console.log("I only run after the previous work completed");
]);
like image 165
Benjamin Gruenbaum Avatar answered Jan 06 '26 11:01

Benjamin Gruenbaum



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!