1

I am trying to use async / await, but the "await" doesn't wait.

What I am trying to achieve is:

  1. fetch data
  2. display data
  3. process data

Each of the above points is a separate function and should be run only when the previous function is done. I have no idea why display data (function 2) is not waiting for fetch data (function 1) to finish.

I have tried to morph the code a few times, but I can't get it to work. I have spent quite a few hours on SO, looking at similair questions, I have read the MDN and quite a few articles on the web about async-await, but I just don't see where I'm making the mistake...

Here is a JSFiddle, but it does not "console.log" the response, so I will also display what the actual browser shows bellow.

Code:

HTML


  <main>

    <div class="d-flex justify-content-around">
        <div class="container row">
          <div class="col-12" id="displayNumbers" style="min-height: 300px; border: 1px solid black;"></div>
          <div class="col-12">
            <div class="btn" id="trigger" style="border: 1px solid red">
              Async / Await
            </div>
          </div>
        </div>
    </div>

  </main>  
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"
    integrity="sha384-oBqDVmMz9ATKxIep9tiCxS/Z9fNfEXiDAYTujMAeBAsjFuCZSmKbSSUnQlmh/jp3" crossorigin="anonymous">
  </script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.min.js"
    integrity="sha384-7VPbUDkoPSGFnVtYi0QogXtr74QeVeeIs99Qfg5YCF+TidwNdjvaKZX19NZ/e6oz" crossorigin="anonymous">
  </script>
  <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

JS


    var displayArea = document.getElementById("displayNumbers");

    async function fetchNumbers(){
      console.log("--fetchNumbers--")
      axios.get("http://numbersapi.com/random/year?json",
      ).then(function (response) {
        console.log("response fetchNumbers data:")
        console.log(response.data);
        numbersData = response.data;
      })
    }

    async function displayNumbers(data){
      console.log("--displayNumbers--")
      console.log(data);
      for (let d in data){
        console.log(d);
        let div = document.createElement("div");
        div.textContent = data[d].toString();
        displayArea.appendChild(div);
      }
    }

    async function processNumbers(){
    console.log("--processNumbers--")
      let divs = displayArea.querySelectorAll("div");
      for (let div of divs){
        const reg = new RegExp('^[0-9]+$');
        if (reg.test(div.textContent)){
          div.style = "background-color: black; color: white;"
        }
      }
    }

    var numbersData = {};
    async function async_numbers(){
      try{
        await fetchNumbers();
        await displayNumbers(numbersData);
        await processNumbers();
      } catch(e){console.log("Error " + e)}
    }

    document.getElementById("trigger").addEventListener("click", async() => {
      async_numbers();
    })

Console.log:

--fetchNumbers--
--displayNumbers--
Object {  }
--processNumbers--
response fetchNumbers data:
Object { date: "April 29", text: "1623 is the year that a fleet of 11 Dutch ships depart for the coast of Peru, seeking to seize Spanish treasure on April 29th.", number: 1623, found: true, type: "year" }

As you can see, --displayNumbers-- doesn't wait for the response fetchNumbers data.

Any help/comments/explanations would be greatly appreciated.

PS: If I can improve the question in any way, let me know.

edit

Error handling on await axios.get

      try{ 
        const response = await axios.get("http://numbersapi.com/random/year?json")       
        console.log("response fetchNumbers data:")
        console.log(response.data);
        return response.data
      }catch(e){console.log("error handling")};
  • 1
    `fetchNumbers()` doesn't return the result of `axios.get()` nor does it `await axios.get()` so it doesn't know you intended it to wait for the get result. – Rocky Sims Dec 10 '22 at 17:50
  • Thank you for a quick response. I have also tried adding `return numbersData` inside `fetchNumbers()` but that didn't change anything. Could you post an anwser (edit fetchNumbers) to show me what you mean? – my-alt-account Dec 10 '22 at 17:54
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – pilchard Dec 10 '22 at 17:55
  • `displayNumbers` and `processNumbers` are fully synchronous functions and don't need to be marked with the `async` keyword. They also don't need to be `await`ed because they are not asynchronous. – slebetman Dec 10 '22 at 17:57

2 Answers2

5

Several issues here:

  • You're missing an await on your axios.get().
  • Using .then() is somewhat an anti-pattern when you're already using async/await.
  • Better to return response.data than assigning it to a global.
  • Also looks like displayNumbers and processNumbers don't need to be async functions.

fetchNumbers() could be rewritten like:

async function fetchNumbers(){
  console.log("--fetchNumbers--")
  const response = await axios.get("http://numbersapi.com/random/year?json")
  console.log("response fetchNumbers data:")
  console.log(response.data);
  return response.data
}


async function async_numbers(){
  try{
    const numbersData = await fetchNumbers();
    // Remove async from both declarations. Not needed.
    displayNumbers(numbersData);
    processNumbers();
  } catch(e){console.log("Error " + e)}
}
Joseph
  • 117,725
  • 30
  • 181
  • 234
  • It's working. Thank you :) The `fetchNumbers` also had a `.catch(function(error){...})` after the `.then` block. How would I implement it in this kind of syntax? – my-alt-account Dec 10 '22 at 18:10
  • 1
    @my-alt-account Wrap the line with `axios.get()` all the way to `return response.data` with a try-catch. That's what async/await enables you to do. However, unless you intend to recover a failing `fetchNumbers()`, I suggest you just let the error happen and let the caller's (`async_numbers()`) try-catch handle it. – Joseph Dec 10 '22 at 18:21
  • all right. thank you. Please check the edit to the question (end of post). Like that? – my-alt-account Dec 10 '22 at 18:25
2

try this:

async function fetchNumbers(){
      console.log("--fetchNumbers--")
      let response = await axios.get("http://numbersapi.com/random/year?json")
      console.log("response fetchNumbers data:")
      console.log(response.data);
      numbersData = response.data;
      
    }