I'm trying to add a polyline to the Google Map generated. The coordinates for the polyline are taken from a JSON file on my web server using jQuery (getJSON function). However, I'm having trouble with callbacks. I've defined three functions in a separate JavaScript file, and these are:
function initMap(callback) {
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: {lat: 34.397, lng: 150.644},
scrollwheel: false,
zoom: 2
});
callback();
}
.
function setPath(callback) {
$.getJSON('./expOneActivityData.json',
function (data) {
//Some looping contstruct to navigate through my JSON file.
}
})
callback();
};
.
function addPath() {
var trekLine = new google.maps.Polyline({
path: expeditionCoordinates,
geodisc: true,
stokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2
});
trekLine.setMap(map);
}
expeditionCoordinates being an array, each element being an object with latitude and longitude property. This is declared as a global variable, with value initialisation happening in setPath()'s loop.
In my HTML file, I have:
<script src="https://maps.googleapis.com/maps/api/js?key=myKey&callback=initMap">
When I try to replace initMap with initMap(setPath(addPath)) in the script tag, I get a 400 Bad request from Google. Ofcourse having just "callback=initMap" in the script tag gives a:
TypeError: callback is not a function
occuring at line with callback() in initMap's definition.
So how can I pass a function to googleapis, where the function itself also has callbacks? (My looping construct is fine btw). I tried adding 'defer' to the googleapi script tag, and also to the one linking to my JavaScript file. I removed all the callbacks stuff, and only excecuted the loop. I hoped the expeditionCoordinates array would finish initialisation before the googleapi script tag is excecuted, though that didnt work either (map still loads, just with no polyline).
I'm fairly new to Javascript and it's asynchronous nature, though I do understand how they work and have been succesfully working with them at a basic level for a week or so.
(Which actually leads me to a side question. Up until now I've only worked with one callback. I would expect something like:
initMap(setPath)
to work as setPath does not have () attached when its definition is passed as a parameter, and hence is not excecuting immediately. Though adding a set of brackets to setPath, as it also takes a callback (addPath), would mean it does get excecuted immediately?)
There are several issues with the provided example:
1) When loading the Google Maps API,
callback
parameter accepts callback function name where the function itself should have the following signature:where
2) Since
jQuery.getJSON()
isasync
by default and you are passing function callback, the implementation ofsetPath
function should like this:Working example
You can, however, add a one-time event listener to mimic sending a callback.
That keeps the callback out of the script
src
URL and your code procedural, though adding the event listener after you're already cut thenew Map
code loose seems a little odd.And note that though its logic is a little more linear, it might not load quite as fast as doing async "the right way" as in Vadim's answer.
You can't pass parameters in the
callback
parameter of the Google Maps Javascript API v3 script include.This won't work:
as you discovered. Something like this should:
Using this to asynchronously load the API: