grazdev
grazdev

Reputation: 1272

How to use async/await syntax with forEach loop in Javascript?

I've looked at several questions on using async/await with a forEach loop but nothing seems to cover my user case... How can I get the code below to work? Right now I'm getting the following error:

await is a reserved word

Here's the code:

export const fetchUserBookmarks = ( bookmarksIDs ) => async ( dispatch, getState, api ) => {

    dispatch({
        type: 'IS_FETCHING_BOOKMARKS'
    });

    try {

        bookmarks = [];

        bookmarksIDs.forEach( bookmarkID => {
            const bookmark = await api.get( selectedPostByIdEP + bookmarkID ); 
            bookmarks.push( bookmark ); 
        }); 

        dispatch({
            type: 'HAS_FETCHED_BOOKMARKS', 
            payload: bookmarks
        });

    } catch( error ) {

        dispatch({
            type: 'FAILED_FETCHING_BOOKMARKS', 
            payload: error
        });

    }

}

Upvotes: 1

Views: 11013

Answers (4)

Nitin Manocha
Nitin Manocha

Reputation: 140

forEach loop is not compatible with promise and async functions. Use for.. of loop instead. It would work fine.

async(data)=>{
    const ids = ["xyz","abc"]
    for (const id of ids){
    let data = await Collection.findById(id)
    console.log(data)
    } 
}

Upvotes: 1

Tal Z
Tal Z

Reputation: 3210

First, To use await you should declare the function as async. You have done so with the outer function but not with the inner function.

The change will look something like this:

bookmarksIDs.forEach(async bookmarkID => {

Second, what you probably want is to run those api calls in parallel.

You can replace forEach with a map call and await all the resulting promises together.

To do that your code should look something like this:

const bookmarks = await Promise.all(
  bookmarksIDs.map(bookmarkID => 
    api.get( selectedPostByIdEP + bookmarkID )
  )
); 

--

It seems that if bookmarks is not declared anywhere else it causes a problem. using const or let should solve that problem.

Upvotes: 8

Ry-
Ry-

Reputation: 224857

forEach isn’t a loop; it’s a function that you pass a function to. There’s no way to get a promise out of it. If you want to perform api.gets one by one, you can use a for loop:

for (const bookmarkID of bookmarksIDs) {
    const bookmark = await api.get(selectedPostByIdEP + bookmarkID); 
    bookmarks.push(bookmark); 
}

and if you want to do them in parallel, you can create several promises and use Promise.all to collect their results:

const bookmarks = await Promise.all(
    bookmarksIDs.map(
        bookmarkID => api.get(selectedPostByIdEP + bookmarkID)
    )
);

Upvotes: 1

Jaromanda X
Jaromanda X

Reputation: 1

You'll want to do something like this instead

try {

    bookmarks = await Promise.all(bookmarksIDs.map( bookmarkID => api.get( selectedPostByIdEP + bookmarkID )); 

    dispatch({
        type: 'HAS_FETCHED_BOOKMARKS', 
        payload: bookmarks
    });

}

Upvotes: 0

Related Questions