Skip to content
Advertisement

Where to place async/await in this case?

EDIT:

The problem was not the placement of the async/await per se, but the fact that I was trying to make a constructor asynchronous.


I have looked through docs, read other questions and answers, but I still can’t get my head wrapped around what function to make async, and where to place the await, to get the behaviour that I want.

Basically, I want the console.log(this.data) in the constructor to log out the data I fetch, but as it is now it logs out a pending Promise.

I have tried literally everything I can think of, I always end up logging out either a Promise, or undefined.

Where can I add async/await in these methods to make it log out the fetched data in the constructor?

If I’m going at this in the compltetly wrong approach, then please let me know.

class Apa {
  
  constructor () {
    
    this.ajaxURL = 'https://example.com/api/';
    this.mockParams = {
      title: 'foo',
      body: 'bar',
      userId: 1
    };
    
    this.data = this.getData(this.mockParams).then(xhr => this.data = JSON.parse(xhr.response)).catch(xhr => this.data = {});
    console.log(this.data);
    
  }
  
  getData(params) {
    
    return new Promise((resolve, reject) => {

      let request = this.postAjax(this.ajaxURL, params);
      request.then((xhr) => {
        resolve(xhr);
      }).catch((xhr) => {
        this.errorMessage = 'Ajax request failed: getData()';
        reject(xhr);
      });

    });
    
  }
  
  postAjax(url, data) {
    
     return new Promise((resolve, reject) => {
            var params = typeof data == 'string' ? data : Object.keys(data).map(
                function(k){ return encodeURIComponent(k) + '=' + encodeURIComponent(data[k]) }
            ).join('&');

            var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
            xhr.open('POST', url);
            xhr.onreadystatechange = function() {
                if (xhr.readyState>3 && xhr.status==200) { resolve(xhr); }
            };
            xhr.onerror = () => reject(xhr);
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
            xhr.send(params);
        });
    
  }
  
}

Note: I know the class doesn’t work as is, I had to replace the real API endpoints with mock up stuff, but I can ensure you that there is no problems in the calls to the real API. The promise (when resolved) does contain the real XMLHttpRequest with the correct response.

Advertisement

Answer

what function to make async

Simple rule: If function contains await, it must be marked async. It changes the semantics of the function so that its return actually becomes resolution of a promise, and will have no traditional return value; it also says execution of parts of it (those following an await) will end up being in the future, as opposed to within the current task.

However, you can’t delay creation of an object (when constructor returns, it must return a constructed object), so constructor cannot be async.

You can still output this.data from code that is within constructor, but not at the time the constructor is executing.

Since constructor must be synchronous in order to construct the object, and AJAX request must be asynchronous(*) in order to give the response time to arrive, I’m letting you know

If I’m going at this in the compltetly wrong approach, then please let me know.


*) This is in fact not true; AJAX call can be synchronous (by passing false as the third parameter of xhr.open), but this is heavily discouraged.

User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement