0

I am trying to learn Javascript Classes and Asynchronous XMLHTTPRequests. I am not too good with Object Oriented Programming and therefore I am attempting to learn it to expand my knowledge.

I have managed to understand how to define Class properties, methods and getters using the mozilla docs at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes.

At the same time I am also learning how to make Asynchronous requests to apis to retrieve data. Please review my stripped down code below, which represents what I am doing to make an Asynchronous request.

Based on the code, I am able to make a successful request and retrieve data from the API request (data logs to console), however the data is not being saved as a property for my object, i.e. even though I have set this.responseData = JSON.parse(http.response);, when i try to access the value of test.responseData, it returns back as undefined.

I have attempted several times to search for a solution online, but unfortunately was unsuccessful and therefore I am posting this question to ask if someone can give me a solution based on my code.

Is what I am attempting possible, or do have to make a synchronous request instead. Many articles online state that using synchrous requests is bad practice and affects broswer rendering?.

Thank you very much and I appreciate your assitance.

class testClass {
  constructor() {
    this.requestApiData();
  }

  requestApiData() {
    let requestUrl = "https://jsonplaceholder.typicode.com/todos/1";
    let http = new XMLHttpRequest();

    http.onreadystatechange = function() {
      console.log("onreadystatechange = ", http.readyState);

      if (http.readyState == 4 && http.status == 200) {
        this.responseData = JSON.parse(http.response);
        console.log("http.response = ", http.response);
      }
    }

    http.open("GET", requestUrl, true);
    http.send();
  }
}


var test;
var count = 0;

function run() {
  count += 1;
  document.getElementById('counter').innerHTML = count + "";

  if (!test) {
    document.getElementById('counter').innerHTML += " - Test Undefined";
    test = new testClass();
  } else {
    document.getElementById('counter').innerHTML += " - Test Defined";
  }

  document.getElementById('output_message').innerHTML = test.responseData;
}

setInterval(run, 3000)
<p id="counter">

</p>
<pre id="output_message">
  
</pre>
SShah
  • 1,044
  • 8
  • 19
  • `this` inside your `onreadystatechange` is not the same as `this` outside it, it's not a reference to the instance you called `requestApiData` on. See the linked question's answers for why and what to do about it. – T.J. Crowder Jan 03 '19 at 22:07
  • 1
    @T.J.Crowder Thank you very much, I have just looked at the other question. So just to better understand, the `this` on `this.responseData = JSON.parse(http.response);` is actually referring to the `http` object and not my actual `testClass` object?.. and to easily fix it I need to declare `var self = this` outside the `onreadystatechange` function declaration, and then use `self.responseData = JSON.parse(http.response);` instead? – SShah Jan 03 '19 at 22:18
  • Yes, that's right. And the `self` solution is *one* possible solution, yes. Others are to use an ES2015+ arrow function for the callback, or use the `bind` method of the function. – T.J. Crowder Jan 04 '19 at 08:47

0 Answers0