Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

javascript

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);
like image 468
Ian Tearle Avatar asked Dec 02 '22 19:12

Ian Tearle


2 Answers

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 {

    }
});
like image 193
Arun P Johny Avatar answered Dec 10 '22 12:12

Arun P Johny


instead of

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

use

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

About method:

open(method,url,async)  

Specifies the type of request, the URL, and if the request should be handled asynchronously or not.

method: the type of request: GET or POST

url: the location of the file on the server

async: true (asynchronous) or false (synchronous)

Source: w3schools

like image 39
Naveenkumar K Avatar answered Dec 10 '22 13:12

Naveenkumar K