3

Tried to push two values to an array to later use the values for db integration. Adding the values to the array is going smoothly, however when fetching the values it returns undefined.

var array = [];

var lat = 54.333;
var lng = 12.556;

array.push(lat, lng);

console.log(array[0]); // Returns undefined

The array looks like this in the console if i just use console.log(array);

Array[0]
- 0: Object
-- 0: 54.333
-- 1: 12.556

Have i missed some sort of hierarchy when trying to display the array?

EDIT: Here is a code-snippet for what exactly dosen't work for me.

var address = 'Champ de Mars, 5 Avenue Anatole France, 75007 Paris,    Frankrike';

var array = [];

$.get('https://maps.googleapis.com/maps/api/geocode/json?address=' +      encodeURIComponent(address), function(data, status) {
      var lat = data.results[0].geometry.location.lat;
      var lng = data.results[0].geometry.location.lng;

      array.push({lat, lng});
  });

console.log(array)

if (array[0] === undefined) {
    console.log('this sucks');
} else {
    console.log('it works');
}
h.johan
  • 33
  • 1
  • 7
  • Your code looks fine.. Note that `console.log` returns `undefined`, but it should print out `array[0]` value. – choz Feb 11 '17 at 03:36
  • `array[0]` is `54.333` like you expect. Are you trying to log this from the console directly? If so, you only need to type `array[0]` to see its value. – the holla Feb 11 '17 at 03:36
  • I do not get undefined from your code. https://jsfiddle.net/f1ym9kwc/ – RoboYak Feb 11 '17 at 03:36
  • 1
    @choz Hmm, wierd. I uploaded a more concrete example on jsfiddle.. https://jsfiddle.net/f1ym9kwc/1/ – h.johan Feb 11 '17 at 03:52

3 Answers3

4

As of your sample in fiddle, It's normal that your array in console is still empty because you're using $.get which does an asynchronous process (AJAX).

In short, you're logging the output before the operation of $.get finishes.

When it finishes, you should see your array has the lat and lng value.

You'll notice the output in console would be like,

var address = 'Champ de Mars, 5 Avenue Anatole France, 75007 Paris, Frankrike';
var array = [];

$.get('https://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(address), function(data, status) {
    var lat = data.results[0].geometry.location.lat;
    var lng = data.results[0].geometry.location.lng;

    /* Array got pushed here */
    array.push({
        lat,
        lng
    });

    /* This console is executed 3rd */
    console.log("Array just got pushed with lat n lng :::", array);
});

/* This console is executed 1st */
console.log("Printing value of array 1 :::", array)


/* These consoles are executed 2nd */
if (array[0] === undefined) {
    console.log('this sucks');
} else {
    console.log('it works');
}

This is the result of your console.log

> Printing value of array 1 ::: []
> this sucks
> Array just got pushed with lat n lng ::: [Object]

Here's your updated fiddle

Edit:

As per your comment, one way to achieve what you want could be something like this.

var getAddressLatLng = function (address) {
    var defer = $.Deferred();

    $.get('https://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(address), function (data) {
        if (data && data.results && data.results.length) {
            var res = data.results[0];

            if (typeof(res) === "object" && res.hasOwnProperty("geometry") && res.geometry.hasOwnProperty("location") && typeof(res.geometry.location) === "object") {
                var lat = res.geometry.location.lat,
                    lng = res.geometry.location.lng;

                if (lat && lng) {
                    defer.resolve({
                        "latitude": lat,
                        "longitude": lng
                    });
                }
            }
        }

        defer.resolve(null);
    });

    return defer;
};

Or if you dont want to use $.gets callback function, You can do;

var getAddressLatLng = function (address) {
    return $.get('https://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(address)).then(function (data) {
        if (data && data.results && data.results.length) {
            var res = data.results[0];

            if (typeof(res) === "object" && res.hasOwnProperty("geometry") && res.geometry.hasOwnProperty("location") && typeof(res.geometry.location) === "object") {
                var lat = res.geometry.location.lat,
                    lng = res.geometry.location.lng;

                if (lat && lng) {
                    return {
                        "latitude": lat,
                        "longitude": lng
                    };
                }
            }
        }

        return null;
    });
}; 

To use it, you can just call the function like;

getAddressLatLng("Champ de Mars, 5 Avenue Anatole France, 75007 Paris, Frankrike").then(function (result) {
    /* result is either 'null' or an object with 'lat' and 'lng' property */
    if (result) {
        console.log("RESULT:: ", result);
        /* And you can do your db operation here */
    }

});
choz
  • 17,242
  • 4
  • 53
  • 73
  • I think i get it now. Super much thanks! Is there any easier way to do this procedure, say if i want to add this information to a database? If not, is there anyway to control when the loading of the API is done? – h.johan Feb 11 '17 at 04:30
  • @h.johan You can do that by executing your code right after the `array` gets pushed which is inside the `$.get` callback function (It's where I put the 3rd console) – choz Feb 11 '17 at 04:34
  • Can i add some kind of `return;` so i don't add a empty field when integrating with the database later on? – h.johan Feb 11 '17 at 04:43
  • `.get` already returns a promise, why do you need to return another promise and and resolve that promise when the `.get` promise is resolved? You could just return the result of `.get`. –  Feb 11 '17 at 22:58
  • @TinyGiant I wasn't returning `$.get`, but executing the result inside its callback function. However, I edited my answer to what you might expect it to be – choz Feb 11 '17 at 23:49
3

console.log shows objects as they are when they are expanded, not how they are when logged.

Because the jQuery get call is asynchronous, at the time array is logged, it is an empty array; but by the time you expand it in the console, the AJAX call has completed and the array is filled. At the time array[0] is logged, array is still an empty array so there is no index at index 0, thus undefined is returned.

You can use console.dir to log the object as it is at the time it is logged:

$.get(url, function(data, status) {
  var lat = data.results[0].geometry.location.lat;
  var lng = data.results[0].geometry.location.lng;
  array.push({ lat, lng });
});

console.dir(array);

var address = 'Champ de Mars, 5 Avenue Anatole France, 75007 Paris, Frankrike';
var array = [];
var url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(address);

$.get(url, function(data, status) {
  var lat = data.results[0].geometry.location.lat;
  var lng = data.results[0].geometry.location.lng;
  array.push({ lat, lng });
});

console.dir(array);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

If you want to run the code after the callback has completed, you can use a .then call:

$.get(url, function(data, status) {
  var lat = data.results[0].geometry.location.lat;
  var lng = data.results[0].geometry.location.lng;
  array.push({ lat, lng });
}).then(function() {
  console.dir(array);

  if (array[0] === undefined) {
    console.log('this sucks');
  } else {
    console.log('it works');
  }
});

var address = 'Champ de Mars, 5 Avenue Anatole France, 75007 Paris, Frankrike';
var array = [];
var url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(address);

$.get(url, function(data, status) {
  var lat = data.results[0].geometry.location.lat;
  var lng = data.results[0].geometry.location.lng;
  array.push({ lat, lng });
}).then(function() {
  console.dir(array);
  
  if (array[0] === undefined) {
    console.log('this sucks');
  } else {
    console.log('it works');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

If you're looking up the coordinates for multiple addresses, you can push the get calls into an array, and use jQuery's $.when. This will only execute once all of the lookups have finished.

var addresses = ['Champ de Mars, 5 Avenue Anatole France, 75007 Paris, Frankrike',
                 'Carrousel de la tour Eiffel, Prom. Quai Branly, 75007 Paris, France'];
var array = [];
var promises = addresses.map(function(address) {
  var url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + encodeURIComponent(address);
  return $.get(url, function(data, status) {
    var lat = data.results[0].geometry.location.lat;
    var lng = data.results[0].geometry.location.lng;
    array.push({ lat, lng });
  });
});

$.when.apply($, promises).then(function() {
  console.dir(array);
  
  if (array[0] === undefined) {
    console.log('this sucks');
  } else {
    console.log('it works');
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Community
  • 1
  • 1
  • Ok, many thanks! So, the function you added in the last example `.then` holds the script until `$.get` is done? – h.johan Feb 11 '17 at 04:40
  • Yes, it's a [promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) –  Feb 11 '17 at 04:42
1

You're seeing undefined because that is the return value of console.log. That is, console.log doesn't have a return value, and so you see undefined in your console.

Shan Plourde
  • 8,528
  • 2
  • 29
  • 42