Why is this function not waiting until it has data from XHR request?

javascript

Solution

Because ajax is asynchronous, means once the request is sent it will continue executing without waiting for the response.

One easy solution is to turn off the asynchronous nature by passing the 3rd parameter to the .open() method as false, but it has drawbacks like the browser thread will be blocked till the request is completed means UI will remain unresponsive till the request is completed.

xhr.open('GET', 'proxy.php?url='+request_url, false);

The correct solution will be is to use a callback method

this.requestData = function(latitude, longitude, callback) {
    request_url = self.API_ENDPOINT + api_key + '/' + latitude + ',' + longitude + '?units=auto';
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = function() {
        if(xhr.readyState==4 && xhr.status==200) {
            content = xhr.responseText;
            if(content != '' && (content)) {
                callback(JSON.parse(content));
            } else {
                callback(false);
            }
        }
    }
    xhr.open('GET', 'proxy.php?url='+request_url, true);
    xhr.send(null);
}
/**
 * Will return the current conditions
 *
 * @param float $latitude
 * @param float $longitude
 * @return \ForecastIOConditions|boolean
 */
this.getCurrentConditions = function(latitude, longitude, callback) {
    this.requestData(latitude, longitude, function(data) {
        if(data !== false) {
            callback(ForecastIOConditions(data.currently));
        } else {
            callback(false);
        }
    });
}



var forecast = new ForecastIO(api_key);
forecast.getCurrentConditions(latitude, longitude, function(condition){
    if(condition !== false) {

    } else {

    }
});

Problem

When I call for getCurrentConditions it tries to return data before requestData has completed and therefore doesn't find data.currently. I am definately getting data returned from the URL, I have tried adding a timeout loop to wait for the XHR to load, but that just broke the script all together. I am kind of confused why the second function is not waiting for this.requestData(latitude, longitude); to finish before continuing. ``` this.requestData = function(latitude, longitude) { request_url = self.API_ENDPOINT + api_key + '/' + latitude + ',' + longitude + '?units=auto'; var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if(xhr.readyState==4 && xhr.status==200) { content = xhr.responseText; if(content != '' && (content)) { return JSON.parse(content); } else { return false; } } } xhr.open('GET', 'proxy.php?url='+request_url, true); xhr.send(null); } /** * Will return the current conditions * * @param float $latitude * @param float $longitude * @return \ForecastIOConditions|boolean */ this.getCurrentConditions = function(latitude, longitude) { data = this.requestData(latitude, longitude); if(data !== false) { return new ForecastIOConditions(data.currently); } else { return false; } } var forecast = new ForecastIO(api_key); var condition = forecast.getCurrentConditions(latitude, longitude); ```

Original source

Related problems