最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why is this function not waiting until it has data from XHR request? - Stack Overflow

programmeradmin6浏览0评论

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);

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);
Share Improve this question asked Apr 18, 2013 at 10:36 Ian TearleIan Tearle 3451 gold badge5 silver badges14 bronze badges 1
  • exact duplicate of How to return the response from an AJAX call? – Bergi Commented Apr 18, 2013 at 10:41
Add a comment  | 

4 Answers 4

Reset to default 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 {

    }
});

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

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

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;
        }
};
发布评论

评论列表(0)

  1. 暂无评论