How To Use Async/Await In a JavaScript Loop

To use async/await with forEach in JavaScript, you need to keep in mind that forEach doesn’t work well with async/await directly. This is because async/await works with Promises, and forEach doesn’t inherently wait for asynchronous operations to complete before moving to the next iteration.

Async/Await with for…of Loop in JS

One common approach is to use for...of loop instead of forEach, as it is well-suited for working with async/await. Here’s an example:

async function myFunction() {
    // You can await here

    for (const item of items) {
        // you can await here
    }
}
async function processItems(items) {
    for (const item of items) {
        await someAsyncOperation(item);
    }
}

async function someAsyncOperation(item) {
    return new Promise((resolve) => {
        // Simulating an asynchronous operation
        setTimeout(() => {
            console.log(`Processed item: ${item}`);
            resolve();
        }, 1000);
    });
}

const itemsToProcess = [1, 2, 3, 4, 5];

// Call the asynchronous function
processItems(itemsToProcess)
    .then(() => {
        console.log('All items processed.');
    })
    .catch((error) => {
        console.error('Error:', error);
    });

In this example, the for...of loop is used to iterate through each item in the array, and the await keyword is used to pause the execution until the asynchronous operation in the someAsyncOperation function is complete.

Do you still prefer using forEach?

If you still prefer using forEach and want to leverage async/await, you can convert it into a for...of loop by converting the array to an iterable using entries() and then destructure the entries:

async function processItems(items) {
    for (const [index, item] of items.entries()) {
        await someAsyncOperation(item);
    }
}

async function someAsyncOperation(item) {
    return new Promise((resolve) => {
        // Simulating an asynchronous operation
        setTimeout(() => {
            console.log(`Processed item: ${item}`);
            resolve();
        }, 1000);
    });
}

const itemsToProcess = [1, 2, 3, 4, 5];

// Call the asynchronous function
processItems(itemsToProcess)
    .then(() => {
        console.log('All items processed.');
    })
    .catch((error) => {
        console.error('Error:', error);
    });

In this modified example, entries() is used to get the index and value pairs, and the loop destructures these pairs into index and item. The await keyword can then be used within the loop as usual.