0
const test = () => {
let shown = { total: 0, thisWeek: 0, thisWeekData: [0, 0, 0, 0, 0, 0, 0] }

modalIds.map(async (data) => {
  await fetch("api/statistics/private/get?modalId=" + data.modalId)
    .then((response) => response.json())
    .then((data) => {
      if (data.success) {
        shown = DataForAllShown(shown, data, "views")


      }
    })
})
return shown
}

The value of shown is always the same as the initial value, but the function DataForAllShown() gives it a new value. When trying to later access the variable it remains the same.

I understand that fetch is always async, but how can I update a variable outside of fetch and access it right after fetching?

Stortal
  • 13
  • 3
  • You have another issue also...overwriting the same variable if more than one request passes the `data.success` condition. What is supposed to happen if more than one is true? – charlietfl May 09 '20 at 20:28
  • This essentially defeats the purpose of a code being asynchronous. You should fetch the data and perform something with that data. Ideally, what you do with your variable `shown`, should be performed inside fetch. – Ehsan Mahmud May 09 '20 at 20:28
  • @charlietfl I am overwriting the same variable because I need to add up the data from multiple fetches. The function DataForAllShown takes in the shown parameter and updates the parameters in it. – Stortal May 09 '20 at 20:34
  • What does "add up the data" mean in more detail? Reassigning the value of `shown` overwrites any previous value as if it never existed – charlietfl May 09 '20 at 20:35
  • @EhsanMahmud I need to add up the data and then return it, I can not do anything with the variable in the fetch because I need the full version of it after fetch is done. – Stortal May 09 '20 at 20:35
  • @charlietfl for example, on the first iteration of mapping the value of shown.total is updated to 2, on the second iteration of mapping it would be updated to 4, etc... – Stortal May 09 '20 at 20:38
  • Providing a sample of expected results will help all from guessing. That explanation is still too vague. In other words an [mcve] – charlietfl May 09 '20 at 20:39
  • What you will need is map the array of fetch promises and use map() properly to store the returned array ...then return resolved Promise.all promise from test() – charlietfl May 09 '20 at 20:41
  • After first iteration of mapping the expected result of shown is:{ total: 2, thisWeek: 2, thisWeekData: [0, 0, 0, 0, 0, 2, 0] }. After second iteration of mapping the expected result of shown is:{ total: 4, thisWeek: 4, thisWeekData: [0, 0, 0, 0, 0, 2, 2] }. I need the final value. – Stortal May 09 '20 at 20:42
  • If `DataForAllShown()` returns the updated object then you need to make `test()` async so it runs through all iterations and returns a promise with final result. – charlietfl May 09 '20 at 20:45
  • Using a `for` loop instead of map() would accomplish that also – charlietfl May 09 '20 at 20:47
  • Ok thanks a lot for your help, will work on fixing it now. – Stortal May 09 '20 at 20:48

1 Answers1

0

What I have noticed is, You have return shown outside of promise. Also using Promise.all() will make more sense for map objects.

Try modifying code something like below:

const test = async () => {
    let shown = { total: 0, thisWeek: 0, thisWeekData: [0, 0, 0, 0, 0, 0, 0] }

    await Promise.all(modalIds.map(async (data) => {
        let response = await fetch("api/statistics/private/get?modalId=" + data.modalId);
        let jsonData = await response.json();
        if (jsonData.success) {
            shown= DataForAllShown(shown, jsonData, "views");
        }
    }));
    
    return shown;

}
Arun Saini
  • 6,714
  • 1
  • 19
  • 22