Question

I am working on a little API, which should display markers on Google Maps. I have a database of possible markers, where I need to set longitude and latitude of the address so I can show them later on the map, without doing geocoding each time for all addresses.

I made a little utility to run it one time and cache these necessary data into database:

function processMissing(data) {
    var result;

    geocoder = new google.maps.Geocoder();
    for (var i=0;i<data.length;i++) {
        geocoder.geocode( { 'address' : data[i]['address']+','+data[i]['city']+','+data[i]['zipcode']+','+data[i]['ctrcode']}, function(results, status) {
            if (status === google.maps.GeocoderStatus.OK) {
               result = data[i]['id'] + ': ' + results[0].geometry.location);
               //Store result to database
            }
        });
    }
}

My only problem is, that data[i]['id'] will of course throw data[i] undefined error, because it does not exists inside of function, which is called async when geocoder is done.

Question is, how can I pass this ID trough geocoder.geocode or how can I reach him inside of function?

Thank you for your help in advance!

Was it helpful?

Solution

Use function closure to associate the id with the callback:

function geocodeAddress(data) {
        geocoder.geocode( { 'address' : data['address']+','+data['city']+','+data['zipcode']+','+data['ctrcode']}, function(results, status) {
            if (status === google.maps.GeocoderStatus.OK) {
               // save the result data in the input structure or write it to your database
               data['id'].result = data['id'] + ': ' + results[0].geometry.location);
               //Store result to database
            } else alert("id ="+data['id']+" could not be geocoded, status:"+status);
        });
}

function processMissing(data) {
    var result;

    geocoder = new google.maps.Geocoder();
    for (var i=0;i<data.length;i++) {
      geocodeAddress(data[i])
    }
}

OTHER TIPS

Not sure if this will solve your problem but I have something similar. Let's give it a try:

// 2.9.1 set address
geocoder.geocode({ address: query.join(" ") }, function (result, status) {
    if (status === google.maps.GeocoderStatus.OK) {
        // center map
        loc = result[0].geometry.location;
        options = $.extend({}, cfg.mapOptions, { center: loc });

        // set map options & markers
        myProject.initMap(options);
        myProject.ajaxGetMarkers(loc.lat(), loc.lng());
    }
});

My query object is similar to your data[i] object. Consider using join(' '):

var query = data[i];
geocoder.geocode({ address: query.join(" ") }, function (result, status) {

});

On success, result[0] will give you address_components, formatted_address, geometry and types. Looks ok on your end. Just added it as extra information.

On your particular problem: Was thinking about using an extra array which can be used to push query or data[i] but then you need 2 separate for loops. Might not be ideal.

On the other hand you could use bind() or $.proxy if you're using jQuery:

var query = data[i];
geocoder.geocode({ address: query.join(" ") }, $.proxy(function (result, status) {
    // this refers to query
}, query));

Using ECMA5 bind is added to the language info:

var query = data[i];
geocoder.geocode({ address: query.join(" ") }, function (result, status) {
    // this refers to query
}.bind(query));

bind is supported from IE9 (info table) if you need older browser support consider using a polyfill as explained on MDN

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top