Home > other >  why is function not waiting until async function finish?
why is function not waiting until async function finish?

Time:01-27

TS Code:

var APIres: any;

export class Component implements OnInit {

 async getInfo(){  
  await this.apicall();
  console.log('API response', APIres)

 }
 
 async apicall(){
   var request = new XMLHttpRequest(); 
   request.open('POST', 'URL', true);
   request.setRequestHeader('Content-Type', 'application/json');
   request.setRequestHeader('Authorization', 'Bearer '   accessToken);
   request.onreadystatechange = async function () {
      console.log('Got Values')
      await res(JSON.parse(this.responseText));
   }
   request.send(content);
 }
}

async function res(x){console.log('out');APIres = x} //Outside of export

Output:

API response undefined
Got Values
out

Desire Output:

Got Values
out
API response res

CodePudding user response:

Adding async doesn't magically cause the function to wait for an event

Wrap your function with a promise

var APIres: any;

export class Component implements OnInit {
  async getInfo() {
    await this.apicall();
    console.log("API response", APIres);
  }

  apicall() {
    return new Promise((resolve) => {
      var request = new XMLHttpRequest();
      request.open("POST", "URL", true);
      request.setRequestHeader("Content-Type", "application/json");
      request.setRequestHeader("Authorization", "Bearer "   accessToken);
      request.onreadystatechange = function () {
        console.log("Got Values");
        resolve(res(JSON.parse(this.responseText)));
      };
      request.send(content);
    });
  }
}

async function res(x) {
  console.log("out");
  APIres = x;
} //Outside of export

CodePudding user response:

Nothing in the code connects the completion of the XHR call with the promise that apicall returns. Although you could wrap XHR in a promise, it makes more sense to use the modern replacement, fetch.

Separately, as VLAZ pointed out in a comment, it's poor practice to populate global data as a side-effect of a method call. Instead, have the methods return the necessary data.

Here's an example using fetch:

export class Component implements OnInit {
    async getInfo() {
        // Note receiving the data as the return value of the method
        const apiData = await this.apicall();
        console.log("API response", apiData);
        return apiData; // Provide the data to the caller
    }

    async apicall() {
        // `fetch` returns a promise of a Response object
        const response = await fetch("/url/here", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
                Authorization: "Bearer "   accessToken,
            },
            body: content,
        });
        // If the response wasn't okay...
        if (!response.ok) {
            // ...fail with an error
            throw new Error(`HTTP error ${response.status}`);
        }
        // The response was okay, read and parse the JSON
        return await response.json();
    }
}
  • Related