[英]AJAX Callback and Javascript class variables assignments
I am trying to build a little javascript class for geocoding addresses trough Google Maps API. 我正在尝试通过Google Maps API构建一些用于对地址进行地理编码的javascript类。 I am learning Javascript and AJAX and I still can't figure out how can I initialize class variables trough a callback: 我正在学习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);
Thank you for helping me out! 谢谢您的帮助!
Thanks TJ for your reply. 感谢TJ的回复。 I read your example and your post — things are getting much clearer. 我阅读了您的示例和您的帖子-事情变得越来越清晰。 But I still have an issue. 但是我仍然有一个问题。 Have a look: 看一看:
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]);
}
Why the alert in initialize() pops before the alert in geoCallback(), printing an undefined/undefined? 为什么initialize()中的警报在geoCallback()中的警报之前弹出,并显示未定义/未定义?
What you need to do is ensure that this
is set correctly in the callback. 什么,你需要做的就是确保this
是在回调中正确设置。 This is sometimes called "binding". 有时称为“绑定”。 Prototype provides Function#bind
for this, but it's easy enough to do if you don't use Prototype — define a function that will do the binding for you: Prototype为此提供了Function#bind
,但是如果您不使用Prototype,它很容易做—定义一个将为您进行绑定的函数:
function bind(context, func) {
return function() {
return func.apply(context, arguments);
}
}
and then use it in your initialize
call: 然后在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]);
}
(Although I think I'd suggest refactoring a bit so that the caller of geoCode
doesn't have to provide the callback at that level.) (尽管我认为我建议您进行一些重构,以便geoCode
的调用者不必在该级别提供回调。)
What bind
above does is create a closure (a function) that, when called, will turn around and call the function you gave with this
set to the context you gave, passing on any arguments that were given. 上面的bind
所做的是创建一个闭包(一个函数),当调用该闭包时,它会转回并调用您使用this
集合提供的函数到您提供的上下文中,并传递给定的所有参数。 (This is done above via Function#apply
, which is a standard part of JavaScript.) You'd normally want to define bind
at a fairly high level (page level or within your scoping function if you use one [which is a good idea]) to avoid having the generated functions closing over more data than necessary. (以上操作是通过JavaScript的标准部分Function#apply
完成的。)通常,您需要在相当高的级别(页面级别或在范围函数内定义bind
,如果您使用一个[ ]),以避免生成的函数关闭多余的数据。
Here's a post in my anemic blog about this
in a bit more detail. 这是我贫乏的博客中有关this
的更详细的信息。
Regarding your edit: That's actually a completely different question. 关于您的编辑:这实际上是一个完全不同的问题。 By default, Ajax calls are asynchronous (which is why Google wants you to provide a callback function). 默认情况下,Ajax调用是异步的 (这就是Google希望您提供回调函数的原因)。 So your code requests the data via getLocations
, but that request is processed asynchronously and your code continues. 因此,您的代码通过getLocations
请求数据,但是该请求被异步处理,您的代码继续。 The very next thing your code does is display the values you don't have yet. 您的代码要做的第二件事是显示您还没有的值。 At some later time, the request will complete and the values will be updated, but by then your code has finished. 稍后,请求将完成并且值将被更新,但是到那时您的代码已经完成。 You'd want to move the alert (more generically, move your code processing the result) into a callback. 您想要将警报(更一般地说,将处理结果的代码移动)移到回调中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.