skip to Main Content

`I’ve made calls to six built-in APIs within a for loop, where each API call depends on the result of the previous one. I’ve attempted to execute these API calls synchronously; however, due to varying response times, achieving true synchronicity has proven challenging.

for (let i = 0; i < 2; i++) {
    let promise1 = new Promise((resolve, reject) => {
        resolve("Promise 1 ");
    });

    let promise2 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("Promise 2");
        }, 1000);
    });

    let promise3 = new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("Promise 3");
        }, 2000);
    });

    let promiseExecution = async () => {
        for (let promise of [promise2, promise3, promise1]) {
            // console.log('promise',promise)
            try {
                const message = promise;
                console.log(message);
            } catch (error) {
                console.log(error.message);
            }
        }
    };
    promiseExecution();
}

Expected:
promise 2
promise 3
promise 1
promise 2
promise 3
promise 1

2

Answers


  1. If your wanting to wait for an array of promises, you can use Promise.all()

    Below is an example, I’ve also used another function run, to also make your loop async, as you also want to await promiseExecution();

    Note: Although this answer seems to give the same result as trincots, there is a difference. trincot has serialized your promises, but here they are in parallel. IOW: trincot’s answer takes about 6 seconds to complete, were this takes about 4 seconds. Now you did say -> API calls synchronously; so technically trincots answer is maybe what your after here, but unless promise2 rely’s on promise1, and promise 3 relies on promise2 then using Promise.all would make more sense.

    async function run() {
        for (let i = 0; i < 2; i++) {
            let promise1 = new Promise((resolve, reject) => {
                resolve("Promise 1 ");
            });
    
            let promise2 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve("Promise 2");
                }, 1000);
            });
    
            let promise3 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve("Promise 3");
                }, 2000);
            });
    
            let promiseExecution = async () => {
                for (let promise of await Promise.all([promise2, promise3, promise1])) {
                    // console.log('promise',promise)
                    try {
                        const message = promise;
                        console.log(message);
                    } catch (error) {
                        console.log(error.message);
                    }
                }
            };
            await promiseExecution();
        }
    }
    
    run();
    Login or Signup to reply.
  2. You’re just missing two await operators. You need one to get the message, and one to await promiseExecution(). For the latter you need to wrap the whole script in an async function.

    However, you create the three promise objects at the same time, so that does not really reflect your actual case where "each API call depends on the result of the previous one". If they are dependent, then you would only create the second promise after the first one resolves, …etc.

    So I would turn these into three functions that when called, create their respective promise:

    const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); // Helper function
    
    // Three functions for creation promises
    const task1 = () => Promise.resolve("Promise 1");
    const task2 = () => delay(1000).then(() => "Promise 2");
    const task3 = () => delay(2000).then(() => "Promise 3");
    
    async function chainOfThree() {
        for (const task of [task2, task3, task1]) {
            const message = await task(); // <---- create promise only now, and await
            console.log(message);
        }
    }
    
    async function main() { 
        for (let i = 0; i < 2; i++) {
            await chainOfThree(); // <---- wait for all three to resolve
        }
    }
    
    main().catch(error => console.log("error", error.message));

    Note that I moved the error handling to the outermost layer, as it is not helpful to catch an error in a middle layer, which then rejects the promise returned by the async function, only to leave that rejection unhandled.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search