0

I am trying to use async and await on my react js app. But it's not working correctly.

const handleFinish = async () => {
    const startDateString = startDate.format('YYYY-MM-DDThh:mm');
    const endDateString = endDate.format('YYYY-MM-DDThh:mm');
    const createdString = moment().format('YYYY-MM-DDThh:mm');
    const requestData = [];
    const previousData = [];
    selectedCustomerData.forEach(customer => {
      selectedProductData.forEach(product => {
        previousData.push({
          customer: customer,
          product: product
        });
      });
    });
    await previousData.forEach(async element => {
      const tempStartDate = moment().add(element.customer.leadtime, 'days');
      const apiUrl = '/productprice/?customerid=' + element.customer.customerid + 
                      '&productkey=' + element.product.productkey + 
                      '&isrulendNull=true';
      await api.get(apiUrl).then(response => {
        let newPrice = 0;
        if (priceMethod === 'fixed') {
          newPrice = price;
        } else if (priceMethod === 'specific') {
          newPrice = response.data[0].productpriceusd + price;
        } else if (priceMethod === 'relative') {
          newPrice = response.data[0].productpriceusd % 100.0 * (100.0 + price);
        }
        requestData.push({
          productkey: element.product.productkey,
          productcode: element.product.productcode,
          customerid: element.customer.customerid,
          customerchain: element.customer.customerchain,
          productpriceusd: newPrice,
          rulestart: (tempStartDate > startDate) ? tempStartDate.format('YYYY-MM-DDThh:mm') : startDateString,
          ruleend: endDateString,
          creatorupn: user.data.displayName,
          created: createdString,
          customername: element.customer.customername,
          productdescription: element.product.productdescription,
        });
      });
    });
    console.log(requestData);
    setPricesList(requestData);
  };

I expected the requestData array after foreach. But that console.log does not occur after foreach, it occurs before foreach. That means async and await is not working. What's wrong in my code?

2
  • have a look here: stackoverflow.com/questions/37576685/… Commented Dec 17, 2020 at 10:36
  • 1
    Generally speaking, you dont want to have both await and then() in your code; either stick to one or the other to avoid problems. In this case as Oleksandr pointed out, you're using .foreach which can't be used with async/await Commented Dec 17, 2020 at 10:40

5 Answers 5

5

I made this mistake quite often myself...

await previousData.forEach(async element => {

this kind of stuff does not synchronize the forEach loop. They are still triggered at the same time, and the await at the beginning of the line does not wait for them. I would use Promise.all or a classic loop like for or while.

Sign up to request clarification or add additional context in comments.

Comments

2

Array.forEach() doesn't wait for all elements to be processed in the given async function.

You can use plain for loop like:

const handleFinish = async () => {
    const startDateString = startDate.format('YYYY-MM-DDThh:mm');
    const endDateString = endDate.format('YYYY-MM-DDThh:mm');
    const createdString = moment().format('YYYY-MM-DDThh:mm');
    const requestData = [];
    const previousData = [];
    selectedCustomerData.forEach(customer => {
      selectedProductData.forEach(product => {
        previousData.push({
          customer: customer,
          product: product
        });
      });
    });

    for (const element of previousData) {
      const tempStartDate = moment().add(element.customer.leadtime, 'days');
      const apiUrl = '/productprice/?customerid=' + element.customer.customerid + 
                      '&productkey=' + element.product.productkey + 
                      '&isrulendNull=true';
      await api.get(apiUrl).then(response => {
        let newPrice = 0;
        if (priceMethod === 'fixed') {
          newPrice = price;
        } else if (priceMethod === 'specific') {
          newPrice = response.data[0].productpriceusd + price;
        } else if (priceMethod === 'relative') {
          newPrice = response.data[0].productpriceusd % 100.0 * (100.0 + price);
        }
        requestData.push({
          productkey: element.product.productkey,
          productcode: element.product.productcode,
          customerid: element.customer.customerid,
          customerchain: element.customer.customerchain,
          productpriceusd: newPrice,
          rulestart: (tempStartDate > startDate) ? tempStartDate.format('YYYY-MM-DDThh:mm') : startDateString,
          ruleend: endDateString,
          creatorupn: user.data.displayName,
          created: createdString,
          customername: element.customer.customername,
          productdescription: element.product.productdescription,
        });
      });
    }

    console.log(requestData);
    setPricesList(requestData);
  };

Comments

0

async/await will not work in forEach loop, you may use for..of loop. here is detailed discussion

Comments

0

async/await is not working correctly on forEach.

Please refer below url.

https://codeburst.io/javascript-async-await-with-foreach-b6ba62bbf404

2 Comments

Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline. Answers that are little more than a link may be deleted
Note to reviewers: I have not flagged this one.
0

With ES2018, you are able to greatly simplify all of the above answers to:

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array);
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.