0

I am having an issue with a class level attribute not being set on object creation. I am using a type of function based class (non ES6) for encapsulating an HTTP request:

/** HttpRequest
*/
function HttpRequest (url) {
    // shell
    this.results = [];

    // base URL
    var baseUrl = url;

    // new promise
    var promiseRequest = new Promise(function(resolve, reject) {
        // new request
        HttpRequest.prototype.requestor(baseUrl, resolve, reject);
    });

    // on promise resolve
    promiseRequest.then(

        /** success
        */
        function success(r) {
            HttpRequest.prototype.addResults(r);
        },

        /** error
        */
        function error(e) {
            console.log("http-request.utility.js: Promise issue");
        }
    );

}

/** HttpRequest.requestor()
  * @param string - API url
  * @param promise callback - resolve
  * @param promise callback - reject
*/
HttpRequest.prototype.requestor = function (apiRequest, resolve, reject) {
    // new page object
    var request = new XMLHttpRequest();

    // event
    request.onreadystatechange = function () {
        if (request.readyState == XMLHttpRequest.DONE) {
            if (request.status == 200) {
                // successful request
                resolve(JSON.parse(request.response));
            }
            else if (request.status == 400) {
                console.log("http-request.utility.js: Error on API request");
            }
            else {
                console.log("http-request.utility.js: Error on API request");
            }
        }
    };

    // iniatilize
    request.open("GET", apiRequest, true);
    request.setRequestHeader("Accept", "application/json; odata=verbose");
    request.send();
}

HttpRequest.prototype.addResults = function (r) {
    this.results = r;
    console.log('ok');
}

When I create an object, and initialize

var p = "api_url";
var ob = new HttpRequest(p);

Everything works as expected on debugging and it appears the array is being updated. However, checking the object attribute returns an empty array:

ob.results # []
Kyle
  • 1,153
  • 5
  • 28
  • 56
  • 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) – ggorlen Aug 11 '20 at 18:53
  • This seems a bit over-engineered, but you can't just `ob.results` which will always run before the promise resolves. You'll need to pass in a callback or return a promise and run `then`/`await` on the returned promise. I recommend using `fetch`, `axios` or a `fetch` polyfill if you're concerned about compatibility. – ggorlen Aug 11 '20 at 18:54

1 Answers1

0

The problem is that you're not passing this to the addResults() method.

function HttpRequest(url) {
  // shell
  this.results = [];

  // base URL
  var baseUrl = url;

  // new promise
  var promiseRequest = new Promise(function(resolve, reject) {
    // new request
    HttpRequest.prototype.requestor(baseUrl, resolve, reject);
  });
  var self = this; // bind closure variable
  // on promise resolve
  promiseRequest.then(

    /** success
     */
    function success(r) {
      self.addResults(r);
    },

    /** error
     */
    function error(e) {
      console.log("http-request.utility.js: Promise issue");
    }
  );

}
Barmar
  • 741,623
  • 53
  • 500
  • 612