2

I'm new on StackOverflow :)

I need help: I'm trying to make an inverse geocode (get an address from coordinates). I have a good URL that works with an ajax. I have many coordinates to convert to address, that is why I'm trying firstly on an array with 4 coordinates on JSfiddle.

What I want for the result is that my script adds all the addresses to my array. I'm trying with a for loop, and on each element of the array, an ajax call which finds the good coordinates.

You can find the call on this link (i put the script after the link) : https://jsfiddle.net/e2wr3umy/

my code which works for an element:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
$.ajax({

                     url: 'https://reverse.geocoder.ls.hereapi.com/6.2/reversegeocode.json',
                      type: 'GET',
                      dataType: 'jsonp',
                      jsonp: 'jsoncallback',
                      data: {
                        prox: '43.564624, 3.847154,250',
                        mode: 'retrieveAddresses',
                        maxresults: '1',
                        gen: '9',
                        apiKey: 'NOT_THE_REAL_API_KEY'
                      },
                      success: function (data) {
                        var re = JSON.stringify(data);
                        console.log(data);
                        var num = (data.Response.View[0].Result[0].Location.Address.HouseNumber);
                        var rue = (data.Response.View[0].Result[0].Location.Address.Street);
                        var ville = (data.Response.View[0].Result[0].Location.Address.City);
                        var CP = (data.Response.View[0].Result[0].Location.Address.PostalCode);
                        console.log(num, rue, CP, ville)
                      }
                    });

Then, I'm trying on an array of 4 elements, this is the link: https://jsfiddle.net/L07pjwba/

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>

var adresse = [['43.564624, 3.847154',1],['43.564624, 3.447154',27],['43.64624, 3.727154',75],['43.564624, 3.617154',254]];


for (i =0; i<adresse.length; i++) {
console.log("element", adresse[i]);
$.ajax({
                      url: 'https://reverse.geocoder.ls.hereapi.com/6.2/reversegeocode.json',
                      type: 'GET',
                      dataType: 'jsonp',
                      jsonp: 'jsoncallback',
                      data: {
                        prox: adresse[i][0].concat(', 250'),
                        mode: 'retrieveAddresses',
                        maxresults: '1',
                        gen: '9',
                        apiKey: 'NOT_THE_REAL_API_KEY'
                      },
                      success: function (data) {
                        var re = JSON.stringify(data);
                        console.log("data", data);
                        var num = (data.Response.View[0].Result[0].Location.Address.HouseNumber);
                        var rue = (data.Response.View[0].Result[0].Location.Address.Street);
                        var ville = (data.Response.View[0].Result[0].Location.Address.City);
                        var CP = (data.Response.View[0].Result[0].Location.Address.PostalCode);
                        adresse[i].push(num, rue, ville, CP);

                      }
                    });

}
console.log("adresse : ",adresse);

But the result is not what I expect: it looks like the ajax call starts after the end of the for loop, even if it is inside the for a loop. I tried with async: false in the ajax, but it didn't change anything.

ElieL
  • 23
  • 3
  • So you are saying the result you get is empty right? Have you seen javascript promises? – HARSHA sss Feb 27 '20 at 10:00
  • Sorry, i mean the result i get in the console.log is not what i expected – ElieL Feb 27 '20 at 10:02
  • could you address me on what you're getting instead of what? – HARSHA sss Feb 27 '20 at 10:04
  • The first link returns "undefined undefined 34430 Saint-Jean-de-Védas" and it's what i expect. But on the second link, i'm getting an error, I get in the consoe.log "element Array [ "43.564624, 3.847154", 1 ]" 4 fimes, then " adresse : Array(4) [ (2) […], (2) […], (2) […], (2) […] ] " and after this TypeError: adresse[i] is undefined 4 times. I'd like the ajax calls before the return of adress, and adress completed. – ElieL Feb 27 '20 at 10:12

1 Answers1

4

This is a common problem stemming from not understanding async. Here is a canonical resource for async issues, but I don't think it would resolve all of your problems, so I won't mark it as a duplicate, but please read it.

Basically, your code tells the geocoding service to let you know about the addresses. Then you print the array. Some time in the future, the geocoding service answers you, but the array is already printed, and JavaScript doesn't have a time machine.

The basic principle is, you can never use the value you obtain from an async function anywhere except in a callback to that function (or its promise chain), and functions that are called from there. In your first snippet you do it correctly: you use console.log inside the callback. In the second snippet, you move it outside the callback, and that is the source of your problems.

Here is how to write it correctly. $.ajax returns a "promise", which you can chain using .then, to specify that something should be done when the promise is fulfilled (i.e. you get a response from the geocoding service). You can use Promise.all to wait for all the promises in an array to be fulfilled. All together, it should look like this (I changed the minimal amount of your code, I'd write it a little bit differently):

var adresse = [
  ['43.564624, 3.847154', 1],
  ['43.564624, 3.447154', 27],
  ['43.64624, 3.727154', 75],
  ['43.564624, 3.617154', 254]
];

var promises = [];
for (i = 0; i < adresse.length; i++) {
  console.log("element", adresse[i]);
  var promise = $.ajax({
    url: 'https://reverse.geocoder.ls.hereapi.com/6.2/reversegeocode.json',
    type: 'GET',
    dataType: 'jsonp',
    jsonp: 'jsoncallback',
    data: {
      prox: adresse[i][0].concat(', 250'),
      mode: 'retrieveAddresses',
      maxresults: '1',
      gen: '9',
      apiKey: 'NOT_THE_REAL_API_KEY'
    },
  }).then(function(data) {
    var num = (data.Response.View[0].Result[0].Location.Address.HouseNumber);
    var rue = (data.Response.View[0].Result[0].Location.Address.Street);
    var ville = (data.Response.View[0].Result[0].Location.Address.City);
    var CP = (data.Response.View[0].Result[0].Location.Address.PostalCode);
    adresse[i].push(num, rue, ville, CP);
  });
  promises.push(promise);
}

Promise.all(promises).then(function() {
  console.log("adresse : ", adresse);
});
Amadan
  • 191,408
  • 23
  • 240
  • 301
  • Okay Thank you for your answer, i will try to find with promises and .then . Nice day to you :) – ElieL Feb 27 '20 at 10:19