0

I was having some problem with javascript asynchronous call. I got a list of addresses, and for each address, I am using geocode to get the latitude and longitude. Then, I proceed to format the marker details and push the marker into a marker array. I have used some promise but it does not seem to work:

var markersToAdd = [];
function drawmap(mapData){
    let promise = new Promise((resolve, reject) => { 
        // getlatlng
        resolve(mapData);
    });
    
    promise.then((markersToAdd) => {
        //loop
        addMarker(markersToAdd[i]);
    });
}

function getLatLng(address, branchName, total){
    geocoder.geocode( { 'address': address }, function(results, status) {

          if (status == google.maps.GeocoderStatus.OK) {
            
          } else {
            alert('Geocode was not successful for the following reason: ' + status);
          }
    });
}

function addMarker(marker) {
    
}

The problem now is the promise is already resolved before I get all the latitude and longitude. My sample output:

It resolved the promise before all the item in the array get its latitude and longitude. By right it is supposed to be print out all details, followed by 'loop finish' and 'done promise'.

How can I fix this?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
QWERTY
  • 2,303
  • 9
  • 44
  • 85

1 Answers1

2

If you start an asynchronous function (.geocode), you may want to await it before you continue. Awaiting in a loop would be possible with await, however in this case itll may be faster to allow racing (all promises starting at once, then continue if all finished) :

At first we need to promisify getLatLng

function getLatLng(address, branchName, total){
     return new Promise(function(resolve){
        geocoder.geocode(function(){
           //do some stuff
           resolve(markerItem);//i think you want to return a new object here right?
        });
     });
}

And then we need to map the mapData to promises, and then unify them with Promise.all:

function drawmap(mapData){
   //a promise to await them all
  //it will resolve to an *markerItem* array, returned from getLatLng
   let promiseKey = Promise.all(
      //map el to getLatLng promise
      mapData.map(el=>getLatLng(el.branchAddress, el.branchName,el.total))
   );
  //... 
  //E.g.
  var addedMarkers = promiseKey.then(
    markers => Promise.all(
      markers.map(marker => addMarker(marker))
    )
  );
 }
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151
  • Hmm sorry but do I perform the for loop under Promise.all or? Also, how do I call the addMarker from the .then() in this case – QWERTY Aug 02 '17 at 11:21
  • @denise tan every code i have left away works as expected. You can still do .then(markersToAdd => . ..) – Jonas Wilms Aug 02 '17 at 11:27
  • @denise tan no need for a loop at all. Thats what .map() does for you. – Jonas Wilms Aug 02 '17 at 11:27
  • @denis tan by the way, eleminate markersToAdd = [], and markersToAdd.push(..) , it will work without that. – Jonas Wilms Aug 02 '17 at 11:29
  • Thanks so much but the strange thing is when I tried to print out from addMarker(), it only printed out branchName and total. The address, lat and lng remains undefined. Any ideas? – QWERTY Aug 02 '17 at 11:39
  • @denis tan ive edited including some ?s... Do you want to call addMarker with the object returned from getLatLng or not? – Jonas Wilms Aug 02 '17 at 11:40
  • Yeah I need to do that. Because I am plotting the marker based on the object returned which contain lat,lng, branchName, branchAddress and total – QWERTY Aug 02 '17 at 11:42
  • @denise tan simply leaving away the .then and resolving the promise to the new marker should do the trick then... – Jonas Wilms Aug 02 '17 at 11:44
  • Thanks it works!!!!! Let me double confirm with you, so what you did was declare a new promise whenever a geocode is called, then you enforce a resolve to return the object. Then once all promise done, you perform a mapping. Then once everything done, it will execute the code inside .then(). Am I on the right track? – QWERTY Aug 02 '17 at 11:51
  • @denis tan well the mapping happens before the promises are done. So you pass an array of promises to promise.all, which resolves to an array of results ( of the promises passed), so the promiseKey.then will be called if all promises are done with an array of markerItems – Jonas Wilms Aug 02 '17 at 11:55
  • Hey do you mind to take a look at this: https://stackoverflow.com/questions/47853456/javascript-promise-not-executing-then It is very similar but I not sure why it does not work – QWERTY Dec 17 '17 at 09:35