I am making an app using the Google maps library. My problem is either there is an unexplicable delay in creating the Markers or I have an asynchronous problem I cannot see.
Explanation : the code fetches Electric Charging Stations Location along a route between a start and an end points, creates Google markers for each station the fetch returns (in Json format) and pushes them in an array. Later it is supposed to calculate a route with stopovers using those markers (not included here).
The problem is it launches the calculation method before it finishes to create the markers.
In order to harmonize results I don't fetch all results at once. Instead I made a loop that does the following :
- create a route and extract an encoded polyline from it (to be used in the URL)
- fetch results
- create markers, set them on map and pushes them on array
- logs in console the job is done ('EV markers creation finished')
Then it launches the route calculation process (here replaced by an alert 'calculateAndDisplayRoute method called)
But in reality the loop finishes and logs in console but the last markers are not created, the alert is launched and only after can you see the markers appear on the map.
You can try the following code snippet :https://codepen.io/reivilo85k/pen/wvowpab
Here is the problematic code (I had to add more code in the codepen in order to make it work though) :
chargingPointsMarkers = [];
markerArray = [];
async callbackHandler(startEndPointsArray, calculateAndDisplayRoute): Promise<void> {
await this.setChargingStationsMarkers();
calculateAndDisplayRoute();
}
function calculateAndDisplayRoute() {
alert('calculateAndDisplayRoute method called')
}
async function setChargingStationsMarkers() {
const polylineMarkersArray = await createMarkersArray();
console.log('Polyline Markers created', polylineMarkersArray);
const baseUrl = 'URL REMOVED';
for (let j = 0; j < polylineMarkersArray.length - 1; j++) {
const origin = polylineMarkersArray[j].getPosition();
const destination = polylineMarkersArray[j + 1].getPosition();
const route = await createRoute(origin, destination);
const encodedPolyline = route.overview_polyline;
const queryUrl = baseUrl + '&polyline='+ encodedPolyline + '&distance=50';
await fetch(queryUrl)
.then((response) => response.json())
.then( async (data) => await createChargerPointMarkers(data))
.then (() => {
const k = j + 1;
const l = polylineMarkersArray.length - 1;
if (j === polylineMarkersArray.length - 2) {
console.log('loop ' + k + ' of ' + l);
console.log('EV markers creation finished');
}else{
console.log('loop ' + k + ' of ' + l);
}
});
}
}
async createChargerPointMarkers(jsonChargingPoints): Promise<void> {
// Convert the Json response elements to Google Markers, places them on the Map and pushes them to an array.
for (const item of jsonChargingPoints) {
const LatLng = new google.maps.LatLng(parseFloat(item.AddressInfo.Latitude), parseFloat(item.AddressInfo.Longitude));
const marker = await new google.maps.Marker({
position: LatLng,
map: this.map,
draggable: false,
});
this.markerArray.push(marker);
this.chargingPointsMarkers.push(marker);
}
}
async createRoute(point1, point2): Promise<google.maps.DirectionsRoute> {
// Returns a Google DirectionsRoute object
const directionsService = new google.maps.DirectionsService();
const request = {
origin: point1,
destination: point2,
travelMode: google.maps.TravelMode.DRIVING,
unitSystem: google.maps.UnitSystem.METRIC
};
return new Promise(resolve => directionsService.route(request,
(result, status) => {
if (status === 'OK') {
resolve(result.routes[0]);
} else {
window.alert('Directions request failed due to ' + status);
}
})
);
}