Dynamically loading the Google Maps API in a Worklight Application
DavidDhuyvetter 10000034CQ Visits (3426)
Loading the Google Map API is a remote call from the Worklight app, and can consume noticeable time at application startup. In some cases, it is worth while to asynchronously load the API, and possibly defer loading the API until a view containing a map is actually shown. Dynamically loading the API has the added benefit of making the GoogleMapWidget more self contained. Up to this point, the widget required that there be a <script /> tag in the HTML to load the API. By dynamically loading the API, the widget will take care of this and not require additional support from the HTML file.
Add functions to support dynamically loading the API
To allow the Google map API to be loaded once, but insure that it is loaded before any instance of the map widget uses the API, we will be using a Deferred object. Everything that we have done up to this point has been encapsulated in the GoogleMapWidget object definition. Using a global Deferred to signal when the API is available allows the widget to be used multiple times in a single app, and allows each instance of the widget to maintain its own state.
In addition to the global Deferred object, we need a global function that can be passed to the API to call back when it has finished loading.
The _mapAPILoaded() function will be called by the Google Map API once it is completely loaded. It simply resolves the Deferred.
We need to declare mapAPIReady at global scope so that mapAPILoaded() can access it, but we can't initialize it until Deferred itself is loaded (inside the require()).
Finally, we need a function to trigger the API loading. Where we call this function will determine if the API is asynchronously loaded as soon as the app is loaded, of if it is only loaded when a view containing a map is displayed.
The loadMaps() function is what launches the asynchronous loading of the Google Map API. Because I'm using dojo 1.7, I use dojo
Another option for loading the Google Map API is to use the Google API Loader. This is probably the best choice if you are using 2 or more Google APIs in your app.
The location of the call to loadMaps() will determine when the API is loaded. It can be called as soon as mapAPIReady is initialized. If it is called in postCreate(), then the API load will begin as soon as the widget is loaded. If it is called in _setupMap(), then the API won't be loaded until the first view that contains a map widget is shown.
Wait until the API is loaded before using it
The above code support kicking off an asynchronous load of the Google Map API, and resolving a Deferred when the API is fully loaded. Now we need to ensure that the API isn't used until the Deferred is resolved. This means that _setupMap() needs to be able to wait before creating the widget's map
Most of the code that was originally in setupMap() has been refactored into createMap(). That function is passed as an argument to _map
Test the completed GoogleMapWidget
I've added two new views to the HTML. When the app starts, the default view is a Home page that allows the user to select one of two views containing maps.
When you click on either of the options, the app transitions to a view containing a map widget
If you visit first Map 1, and then Map 2, and then look at the series of calls in the console log, you will see that the Google Map API is loaded when the first view containing a map is displayed, and simply reused when the second view is displayed.
I may revisit this app as an example to illustrate some uses of Worklight adapters, but for now, it is done. The sample project can be downloaded here.