6

I'm currently working with Google maps' geocoding and need to create an array that will contain arrays as an elements.

Basically i need to create this:

    var locations = [
      ['Bondi Beach', -33.890542, 151.274856, 4],
      ['Coogee Beach', -33.923036, 151.259052, 5],
      ['Cronulla Beach', -34.028249, 151.157507, 3],
      ['Manly Beach', -33.80010128657071, 151.28747820854187, 2],
      ['Maroubra Beach', -33.950198, 151.259302, 1]
    ];

But dynamically! I need this array to put pins on a map later.

What I'm doing:

        var locations = []; // The initial array
        for (var i = 0; i < addresses.length; ++i){

            var address=addresses[i]; // the address e.g. 15 Main St, Hyannis, MA
            geocoder.geocode({ 'address': address}, function(results){
                var obj = {
                    0: address,
                    1: results[0].geometry.location.hb,
                    2: results[0].geometry.location.ib,
                    3: i
                };
                console.log(obj);
                locations.push(new Array());
                locations[i].push(obj);

            });
        };

        console.log(locations.length);

The problem, question:

I don't see any errors but at the end locations[] array is empty.

Here is a console screen if needed:

3
  • 3
    geocode is async. You need to wait for ALL calls to reply before processing the array. Commented Mar 1, 2013 at 16:20
  • Hm. I thought loop should be finished for script to continue? no? Commented Mar 1, 2013 at 16:26
  • The basic way to push an empty array into another away isn't obvious in this question, so I'll point out that for an array it's myArray.push(new Array()). myArray must at least be instantiated to an empty array i.e. myArray = [] Commented Aug 22, 2018 at 6:50

2 Answers 2

2

This should be all you need:

geocoder.geocode({ 'address': address}, function(results){
            locations.push([
              address,
              results[0].geometry.location.hb,
              results[0].geometry.location.ib,
              i //this is actually going to always be 
                //addresses.length because the callback won't fire
                //until well after the loop has completed. 
                //Is this really a necessary field to have 
                //in your array? if so, you'll need to refactor a bit
            ]);
        });
4
  • Makes sense... but console.log(locations.length); still shows 0 Commented Mar 1, 2013 at 16:22
  • 2
    @rinchik probably because geocoder.geocode() is async... and locations hasn't changed by the time you log it. Commented Mar 1, 2013 at 16:23
  • See Prinzhorn's comment on your question...it's async, you need to only fire the console.log after all geocodes have been finished Commented Mar 1, 2013 at 16:23
  • 1
    @BLSully you should mention that i will always be addresses.length because of scoping Commented Mar 1, 2013 at 16:31
1

i didn't have time to test the code, but it should work this way:

    function requestLocations( addresses, callback ) {
        var remainingLocations = addresses.length;
        var locations = [];

        for (var i = 0; i < addresses.length; ++i){

            var address=addresses[i]; // the address e.g. 15 Main St, Hyannis, MA

            locations[i] = [];

            geocoder.geocode({ 'address': address}, (
                function(idx) {
                    return function(result) {
                        locations[idx] = [  addresses[idx], 
                                            results[0].geometry.location.hb,
                                            results[0].geometry.location.ib,
                                            idx
                                        ];

                        //decrement the number of remaining addresses
                        --remainingLocations;

                        //if there are no more remaining addresses and a callback is provided then call this calback with the locations
                        if( remainingLocations === 0 && callback ) {
                            callback(locations);
                        }               
                    }; // returns the real callback function for your geocoding

                })(i) //direct invocation of function with paramter i for scoping
            );

        }
    }


    requestLocations(addresses, function( locations ) {
        console.dir(locations);
        console.log(locations.length);
    });

The Problem with your code is the following. First this part of the code is executed:

        var locations = []; // The initial array
        for (var i = 0; i < addresses.length; ++i) {

            var address = addresses[i]; // the address e.g. 15 Main St, Hyannis, MA
            geocoder.geocode({
                'address': address
            }, function(results) {
                //this part is called later when that data is ready (it is an asynchronous callback)

            });
        };

        //because of the async request this is still 0
        console.log(locations.length);

After that the callbacks itself are called as soon as the browser receives the data from the server:

      function(results) {
        var obj = {
            0: address,
            1: results[0].geometry.location.hb,
            2: results[0].geometry.location.ib,
            3: i
        };
        console.log(obj);
        locations.push(new Array());
        locations[i].push(obj);

      }
3
  • Awesome! :D Just tested it! IT WORKS! Thank you for detailed answer and work on my code :) +1 Commented Mar 1, 2013 at 16:58
  • 1
    @rinchik there was a bug in it addresse should have been addresses[idx] in the callback. please recheck your code, otherwise you will always have the same address in your result. Commented Mar 1, 2013 at 17:00
  • Hmm... quick question! for some reason for (var i = 0; i < addresses.length; ++i) loop loops only 12 times and then stops. If i put console.log(remainingLocations); here is the output: screencast.com/t/ENbhFdpaDRcE Do you have any idead why this might be happening? Commented Mar 1, 2013 at 20:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.