1

How can one create a for loop that waits for an asynchronous call to complete prior to starting a new iteration of a loop WITHOUT a library (like jQuery)?

Example:

var items = [1,2,3,4,5];

for (var i = 0; i < items.length; i++) {

    var promise = new Promise(function(resolve, reject){
        asyncAPIcall({
            body : item[i]
        }, function(error, response){
            if(error) {
                reject();
            } else {
                resolve();
            }
        });

    promise.then(function() {
            //continue loop
        }, function() {
            //break loop
        });

}

Thanks


UPDATE (4/29)

I thought of this solution, where I create a function that calls itself:

var items = [1,2,3,4,5];

var counter = items.length - 1; //minus one since array is zero based.

function myLoop(){

    asyncAPIcall({
        body : item[counter]
    }, function(error, response){
        if(error) {
            // Error message.
        } else {
            counter = counter - 1;
            if(counter == -1){
                //Done
            }
            else {
                myLoop();
            }
        }
    });

}

7
  • You can't. What do you really need to do? Commented Apr 27, 2016 at 21:46
  • A for loop is synchronous. It can never wait for an asynchronous operation. You can have a queue though or something similar. Commented Apr 27, 2016 at 21:48
  • @Amit I need to fire of a long series of API calls and if one fails, stop the chain of an additional calls. I am interacting with an API that only accepts one object at a time, so I have to hit it like 20 times to send all my objects. Commented Apr 27, 2016 at 21:51
  • @FelixKling any recommendations? Commented Apr 27, 2016 at 21:51
  • 1
    stackoverflow.com/q/28683071/218196 Commented Apr 27, 2016 at 21:53

1 Answer 1

3

You can use reduce to make them process sequentially (or set up the promise chain using a regular for loop -- I prefer reduce, myself).

let promise = items.reduce((carry, current) => {
    return carry.then(arr => {
        return asyncAPIcall({ body: current }).then(result => arr.concat([ result ]));
    });
}, Promise.resolve([]));

promise.then(finalResult => {
    console.log('final result:', finalResult);
});

This may be more than you need, if you don't actually need to capture the results of those promise resolutions, though. Also note that you'll still have a promise at the end of it, which will contain an array of the results of each promise, corresponding to their original array position.

Also, here is a mocked version of the asyncAPIcall, which should assist with showing the order of operations here, if you want to trace through how / where the methods are called.

function asyncAPIcall(obj) {
    console.log('asyncAPIcall for:', obj);
    return new Promise((resolve) => {
        setTimeout(() => {
            let resolution = obj.body + 5; // change the value in some way, just to show that input !== output
            console.log('resolving with:', resolution);
            return resolve(resolution);
        }, 100);
    });
}
Sign up to request clarification or add additional context in comments.

2 Comments

I'll give it a try. Thanks for the recommendation!
Good luck! If you don't need the results at the end, a lot of the array shenanigans can go away entirely. If you need, I can add a simpler version that doesn't care about the results.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.