0

I use fetch to get data for each element of an array. Those values are pushed into an array and I want to return the max of those values once all values are fetched.

For that I used a promise:

 async function init() {
     await maxWaste(nut0Codes).then(response => {
         console.log(response);
     });
 }

 function maxWaste(nutCodes) {
     return new Promise(resolve => {
         let waste = [];
         nutCodes.forEach((element) => {
             let query = queryMaxWaste(element);
             fetch(address + encodeURIComponent(query))
                 .then(response => {
                      return response.json();
                  })
                 .then(response => {
                        waste.push(response.results.bindings[0].wasteGeneration.value);
                        console.log(waste);
                 });
         });
         let maxWaste = Math.max(waste);
         resolve(maxWaste);
     });
 }

I am not sure where my mistake is but the resolve happens before the fetch is done :

enter image description here

I receive the zero from the console.log(response) and I don't know why it is not working.

Any advice would be appreciated!

5
  • 2
    You're never awaiting your fetch. Commented Jan 22, 2019 at 20:53
  • How can I do that? If I write await fetch(...)I get an error Commented Jan 22, 2019 at 20:55
  • You need to resolve in your last .then on fetch Commented Jan 22, 2019 at 20:57
  • You can't the way it is written currently, the promises would be lost inside forEach. Write a manual for-each loop, then you can await each fetch. Commented Jan 22, 2019 at 20:58
  • Actually upon further inspection... you need to push those promises to an array and use Promise.all Commented Jan 22, 2019 at 20:58

1 Answer 1

3

If you're going to write code that uses async, you should actually leverage async. If this needs to be run synchronously-ish, you can await within a for loop. If you want them all to run simultaneously, use a map and Promise.all.

async function init() {
  const response = await maxWaste(nut0Codes);
  console.log(response);
}

async function maxWaste(nutCode) {
  const waste = [];

  for (const element in nutCode) {
    const query = queryMaxWaste(element);
    const response = await fetch(address + encodeURIComponent(query));
    const json = await response.json();
    waste.push(json.results.bindings[0].wasteGeneration.value);
    console.log(waste);
  }
  const maxWaste = Math.max(waste);
  return maxWaste;
}

You could also try writing it like this so that you don't wait for each response to complete before running the next fetch:

async function init() {
  const response = await maxWaste(nut0Codes);
  console.log(response);
}

async function maxWaste(nutCode) {
  const waste = await Promise.all(nutCode.map(async element => {
    const query = queryMaxWaste(element);
    const response = await fetch(address + encodeURIComponent(query));
    const json = await response.json();
    return json.results.bindings[0].wasteGeneration.value;
  }));

  return Math.max(waste);
}
Sign up to request clarification or add additional context in comments.

1 Comment

@ViktorG See my edit for a way to do all requests simultaneously.

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.