0

In the beginning, I was using forEach like this:

products.forEach(async (product) => {
    if (
      product.type === 'shows' &&
      product.isSoldOut &&
      product.otherData
    ) {
      delete product.brand.brandId
      product.brand.isTop = true
      const res = await api.create(product.brand)
      console.log(res)
    }
  })

But issue was that it was getting called after the other calls while should be called before them. After checking some answers in here I switched into for of loop for forcing it to call before the other async operations located after it. But the issue is that it's not getting called at all now. Here is the code:

for (const product of products) {
        async () => {
    if (
      product.type === 'shows' &&
      product.isSoldOut &&
      product.otherData
    ) {
      delete product.brand.brandId
      product.brand.isTop = true
      const res = await api.create(product.brand)
      console.log(res)
    }
  }
}

What is wrong? It doesn't get called at all, and how can I force this async calls locaded in the loop get called before the calls located after it?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
  • `async () => { ... }` - what is this nested function (that you never call) doing inside the for-of loop? – Yousaf Mar 06 '21 at 09:53

1 Answers1

0

Your code just repeatedly creates and then throws away an async function it never calls. But even calling it wouldn't have helped.

If the containing function (the function in which this code appears) is not an async function, that function's logic will always complete before you can see any of the results of those asynchronous actions. You can't directly observe an asynchronous result in a synchronous function. You can use Promise.all and map to get a callback when the operations complete:

// In a non-`async` function
Promise.all(products.map(async (product) => {
    if (
        product.type === 'shows' &&
        product.isSoldOut &&
        product.otherData
    ) {
        delete product.brand.brandId
        product.brand.isTop = true
        const res = await api.create(product.brand)
        console.log(res)
    }
}))
.then(() => {
    // It's all done now
})
.catch(error => {
    // There was an error
});

Those promise completion callbacks won't run until the containing function has returned. Also note that the operations happen in parallel (all get started and run overlapping), not in series (one at a time). (It's also possible to do this in series, but your forEach was parallel, so...)

If the containing function is an async function, you could switch to for-of instead if you wanted:

// In an `async` function
for (const product of products) {
    if (
        product.type === 'shows' &&
        product.isSoldOut &&
        product.otherData
    ) {
        delete product.brand.brandId
        product.brand.isTop = true
        const res = await api.create(product.brand)
        console.log(res)
    }
}

Note that that will start each operation in series, waiting to start the next one until the previous one completes.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875