DEV Community

Cover image for Handle Multiple Promises using Async/Await
Matthew Wang
Matthew Wang

Posted on

8 6

Handle Multiple Promises using Async/Await

In this example below, we loop through an Array of userIDs to fetch information about the user.

A naive approach may be to await each response one by one.

❌ The wrong and slow way

userIDs = ['fooID1', 'fooID2', ...]
const slowMethod = async (userIDs) => {
    const results = [];
    for (let i = 0; i < userIDs.length; i++) {
        const res = await fetch(`https://api.foo.com/users?uid=${userIDs[i]}`)
        const data = await res.json()
        results.push(data);
    }
    return results;
}
await slowMethod(); //O(n) time
Enter fullscreen mode Exit fullscreen mode

✔️ The Fast Way

userIDs = ['fooID1', 'fooID2', ...]
const fastCleanMethod = async (userIDs) => {
    const promises = userIDs.map(async userID => {
        const res = await fetch(`https://api.foo.com/users?uid=${userID}`);
        return await res.json();
    });
    return await Promise.all(promises);
}
await fastCleanMethod(); //O(1) time
Enter fullscreen mode Exit fullscreen mode

🧐 How it works

The fast method takes advantage of the Promise.all() method. The way it works is by fetching all the data first, then using Promise.all() to resolve/reject later.

By doing this, we do not have to wait for each response one by one.

Another Example of two separate fetches

Let's say we want to fetch user data and their entries. Here are two ways to do it.

❌ Fast but Fails Slow

const getUserData = async (userIDs) => {
    const userDataPromise = fetch(`https://api.foo.com/users?uid=${userID}`);
    const userEntriesPromise = fetch(`https://api.foo.com/entries?uid=${userID}`);

    const [userDataRes, userEntriesRes] = [(await userDataPromise).json(), (await userEntriesPromise).json()];
    const [userData, userEntries] = [await userDataRes, await userEntriesRes];
    return {
        ...userData,
        userEntries,
    }
}
Enter fullscreen mode Exit fullscreen mode

This method works well in most cases but if the second Promise is rejected bad things can happen. The reason it fails slow is because if the second Promise is rejected, the first Promise still runs for the whole duration.

Stack Overflow user @T.J. Crowder explains parallel Promise patterns best here.

✔️ Fast and Fails Fast

const getUserData = async (userIDs) => {
    const userDataPromise = fetch(`https://api.foo.com/users?uid=${userID}`);
    const userEntriesPromise = fetch(`https://api.foo.com/entries?uid=${userID}`);

    const [userDataRes, userEntriesRes] = await Promise.all([userDataPromise, userEntriesPromise]);
    const [userData, userEntries] = await Promise.all([userDataRes.json(), userEntriesRes.json()]);
    return {
        ...userData,
        userEntries,
    }
}
Enter fullscreen mode Exit fullscreen mode

We use Promise.all() because when a Promise is rejected, it immediately throws an error without waiting for other Promises.

It may be tempting to use pure async/await for handling multiple Promises but Promise.all() is still our best bet.

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS Security LIVE!

Hosted by security experts, AWS Security LIVE! showcases AWS Partners tackling real-world security challenges. Join live and get your security questions answered.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️