【问题标题】:AJAX Callback and Javascript class variables assignmentsAJAX 回调和 Javascript 类变量赋值
【发布时间】:2010-03-26 10:59:59
【问题描述】:

我正在尝试通过 Google Maps API 为地址地理编码构建一个小的 javascript 类。我正在学习 Javascript 和 AJAX,但我仍然不知道如何通过回调初始化类变量:

    // Here is the Location class, it takes an address and 
    // initialize a GClientGeocoder. this.coord[] is where we'll store lat/lng
    function Location(address) {
        this.geo = new GClientGeocoder();
        this.address = address;
        this.coord = [];                        
    }

    // This is the geoCode function, it geocodes object.address and 
    // need a callback to handle the response from Google
    Location.prototype.geoCode = function(geoCallback) { 
        this.geo.getLocations(this.address, geoCallback); 
    }

    // Here we go: the callback. 
    // I made it a member of the class so it would be able 
    // to handle class variable like coord[]. Obviously it don't work.
    Location.prototype.geoCallback = function(result) {
        this.coord[0] = result.Placemark[0].Point.coordinates[1];
        this.coord[1] = result.Placemark[0].Point.coordinates[0];
        window.alert("Callback lat: " + this.coord[0] + "; lon: " + this.coord[1]);
    }

    // Main
    function initialize() {
        var Place =  new Location("Tokyo, Japan");
        Place.geoCode(Place.geoCallback);
        window.alert("Main lat: " + Place.coord[0] + " lon: " + Place.coord[1]);
    }

    google.setOnLoadCallback(initialize);

谢谢你帮助我!

编辑

感谢TJ 的回复。我读了你的例子和你的帖子——事情变得更清楚了。但我还有一个问题。看看:

function bind(context, func) {
    return function() {
        return func.apply(context, arguments);
    }
}
function Location(address) {
    this.geo = new GClientGeocoder();
    this.address = address;
    this.coord = [];                        
}

Location.prototype.geoCode = function(callback) { 
    this.geo.getLocations(this.address, callback); 
}

Location.prototype.geoCallback = function(result) {
    this.coord[0] = result.Placemark[0].Point.coordinates[1];
    this.coord[1] = result.Placemark[0].Point.coordinates[0];
    // This alert is working properly, printing the right coordinates
    window.alert("I am in geoCallback() lat: " + this.coord[0] + "; lon: " + this.coord[1]);
}

function initialize() {
    var Place =  new Location("Tokyo, Japan");
    Place.geoCode(bind(Place, Place.geoCallback));
    window.alert("I am in initialize() lat: " + Place.coord[0] + "; lon: " + Place.coord[1]);
}

为什么 initialize() 中的警报在 geoCallback() 中的警报之前弹出,打印一个未定义/未定义?

【问题讨论】:

  • initialize() 中的警报在geoCallback() 中的警报之前弹出,因为getLocations 是异步的(AJAX 代表异步 Javascript...)。

标签: javascript ajax callback geocoding google-maps


【解决方案1】:

您需要做的是确保在回调中正确设置this。这有时被称为“绑定”。 Prototype 为此提供了Function#bind,但如果您不使用 Prototype,这很容易做到——定义一个为您执行绑定的函数:

function bind(context, func) {
    return function() {
        return func.apply(context, arguments);
    }
}

然后在您的initialize 通话中使用它:

function initialize() {
    var Place =  new Location("Tokyo, Japan");
    Place.geoCode(bind(Place, Place.geoCallback)); // <= Change is here
    window.alert("Main lat: " + Place.coord[0] + " lon: " + Place.coord[1]);
}

(虽然我认为我建议进行一些重构,以便geoCode 的调用者不必提供该级别的回调。)

上面的bind 所做的是创建一个闭包(一个函数),当调用该闭包时,它将转身并调用您提供的函数,并将this 设置为您提供的上下文,并传递给定的任何参数。 (这是通过 Function#apply 完成的,这是 JavaScript 的标准部分。)您通常希望在相当高的级别(页面级别或在您的范围函数中定义 bind,如果您使用 [这是好主意]) 以避免生成的函数关闭过多的数据。

Here's a post 在我贫血的博客中更详细地介绍了this


关于您的编辑:这实际上是一个完全不同的问题。默认情况下,Ajax 调用是异步(这就是 Google 希望您提供回调函数的原因)。因此,您的代码通过getLocations 请求数据,但该请求是异步处理的,您的代码会继续执行。您的代码要做的下一件事是显示您还没有的值。稍后,请求将完成并且值将被更新,但此时您的代码已经完成。您希望将警报(更一般地,将处理结果的代码)移动到回调中。

【讨论】:

  • 感谢您的澄清回复和链接!但我仍然对 AJAX 有疑问,我编辑了问题。
  • @Gianluca:您编辑的问题实际上是一个完全不同的问题,最好单独提出一个问题而不是编辑这个问题。
  • @Gianluca: ...但我继续在上面发布了答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-26
  • 2014-03-22
  • 2016-09-10
  • 1970-01-01
  • 1970-01-01
  • 2021-02-17
  • 2017-07-01
相关资源
最近更新 更多