4

当我调用 getCurrentConditions 时,它会尝试在 requestData 完成之前返回数据,因此找不到 data.currently。我肯定会从 URL 返回数据,我尝试添加一个超时循环来等待 XHR 加载,但这只是一起破坏了脚本。我有点困惑为什么第二个函数不等待 this.requestData(latitude, longitude); 在继续之前完成。

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

4 回答 4

13

因为 ajax 是异步的,这意味着一旦发送请求,它将继续执行而不等待响应。

一种简单的解决方案是通过将第三个参数传递给.open()方法作为 false来关闭异步特性,但它有一些缺点,例如浏览器线程将被阻塞直到请求完成意味着 UI 将保持无响应直到请求完成完全的。

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

正确的解决方案是使用回调方法

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 {

    }
});
于 2013-04-18T10:39:45.860 回答
4

代替

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

利用

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

关于方法:

open(method,url,async)  

指定请求的类型、URL 以及是否应异步处理请求。

method:请求类型:GET 或 POST

url:服务器上文件的位置

async:true(异步)或 false(同步)

资料来源:w3schools

于 2013-04-18T10:51:52.363 回答
1

放在这里false而不是true

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

这使得调用同步而不是同步。因此,当调用变为同步时,它会等待 ajax 调用完成,然后执行您想要的功能。

XMLHttpRequest 的 Mozila 链接:同步和异步请求

于 2013-04-18T10:39:02.873 回答
1

这是异步调用。尝试使用回调函数。下面的代码是一个示例。未测试!

 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;
        }
};
于 2013-04-18T10:40:16.700 回答