'JavaScript promise skipped for loop and resolved straight away

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?



Solution 1:[1]

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))
    )
  );
 }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1