5

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);
Ian Tearle
  • 342
  • 1
  • 5
  • 14
  • exact duplicate of [How to return the response from an AJAX call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – Bergi Apr 18 '13 at 10:41

4 Answers4

13

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 {

    }
});
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
4

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

NamingException
  • 2,388
  • 1
  • 19
  • 41
  • I thought the true/false was swapped and spent so much time on this (thinking I'd already found and set the correct param, wondering why it didnt' wait)! Thanks for clear answer! – FreeSoftwareServers Jan 10 '22 at 03:54
2

put false instead of true here

// `false` makes the request synchronous
xhr.open('GET', 'proxy.php?url='+request_url, false);

this make call Synchronous instead of aSynchronous. so when call become Synchronous its wait for ajax call to complete and than execute the function you want.

Mozila link for XMLHttpRequest: Synchronous and asynchronous requests

Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
  • 1
    Don't forget to advise against sjax! – Bergi Apr 18 '13 at 10:45
  • Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/. – cainhs Apr 28 '16 at 03:36
1

It's asynch call. Try to use callback function. Code below is a sample. Not tested!

 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 {
                    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) {
        this.requestData(latitude, longitude, callback);        
    }

this.callback = function(data) {
if(data !== false) {
            return new ForecastIOConditions(data.currently);
        } else {
            return false;
        }
};
Dmitry Volokh
  • 1,630
  • 16
  • 28
  • Yes, it looks untested and misses to propagate the callback style. You're still `return`ing. – Bergi Apr 18 '13 at 10:43