javascriptajaxcallbackrevealing-module-pattern

Returning data resolved by XMLHttpRequest with module pattern function


I have problem combining javascript callbacks and revealing module pattern. What I'm trying to do is to return the HTTP response text with the carsData.getCars() function method.

Basically what I want to do is:

  1. return the data from xhr.onreadystatechange function to the private getData function
  2. return the data from getData function to the public getCars function ( or call the getCars function returning a value)

I got it to work with the synchronous AJAX mode, but I'm aware it's not the best practice in javascript development.

I tried to get it to work with callbacks but failed miserably. Is it even posible to do in javascript?

P.S. I use XMLHttpRequest in Vanilla JS instead of other frameworks for learning purposes.

'use strict';
var carsData = (function() {
    var carsElement = document.getElementById('carsListing'),
        successHandler = function(data) {
            carsElement.innerHTML = data.data;
            //return data;
        },
        dataWrapper = "",
        getData = function(callback) {
            var url = 'data/cars.json',
                xhr = new XMLHttpRequest();    

            xhr.onreadystatechange = function() {
                var status;
                var data;

                if (xhr.readyState == 4) { // `DONE`
                    status = xhr.status;
                    if (status == 200) {
                        data = JSON.parse(xhr.responseText);
                        successHandler && successHandler(data);
                        callback(data);
                        return data;
                    }
                }
            };
            xhr.open('get', url, false); // synchronous js
            xhr.send();
            return xhr.onreadystatechange();
            //return 'xx';
        }

    return {
        getCars: function() {
            return getData(function(data){
              console.log(data); // Object {data: Array[5]}
            })
        }

    }
})();

Solution

  • No. You cannot do it this way. I figured out that is why you typically see results sent to a DOM object. Because they are there waiting for the answer. Your return statement, as counter-intuitive as it seems (assuming you are coming from non-prototype languages), will have already run. It seems like it wouldn't but it has because of the async nature you are aware of. You have to use Promises or you have to have your callback doing something with the data that is "waiting" for the callback data like you did with successdata.