Can Google Maps be initialized asynchronously without the need for a global callback function?

Currently, I am working on developing a reusable drop-in Module that can load Google Maps asynchronously and return a promise.

If you want to take a look at the code I have constructed for this using AngularJS, you can find it here.

One issue I have encountered is the drawback of establishing a global callback function "behind the scenes." This could potentially lead to conflicts with other libraries if they happen to use the same namespace.

So, my main question here is whether there is an alternative approach to achieve this functionality without relying on global variables.

Below is a snippet of the code responsible for creating the problematic global callback:

// In order to initialize Google Maps asynchronously, a global function is required
angular.module('GoogleMapsInitializer')
    .factory('Initializer', function($window, $q){

        // Deferred object for loading maps
        var mapsDefer = $q.defer();

        // URL for async maps initialization accepting callback function
        var asyncUrl = 'https://maps.googleapis.com/maps/api/js?callback=';

        // Function for async loading
        var asyncLoad = function(asyncUrl, callbackName) {
          var script = document.createElement('script');
          script.src = asyncUrl + callbackName;
          document.body.appendChild(script);
        };

// The culprit:

        // Callback function - resolves promise once maps are loaded successfully
        $window.googleMapsInitialized = function () {
            mapsDefer.resolve();
        };

        // Load Google Maps
        asyncLoad(asyncUrl, 'googleMapsInitialized');

        return {

            // Usage: Initializer.mapsInitialized.then(callback)
            mapsInitialized : mapsDefer.promise
        };
    })

Answer №1

When it comes to retrieving data from a server located on a cross-origin domain, the technique you are discussing is known as JSONP. More information about JSONP can be found here. Essentially, JSONP requires calling a globally scoped function to function properly.

In response to your query, JSONP cross-origin techniques cannot operate without the use of a global function. This is inherent to how the mechanism functions - scripts must be executed in the global namespace and connect with a function available within that global scope. Even popular libraries like jQuery and YUI adhere to this concept when implementing JSONP.

If you are utilizing Angular, you're in luck as JSONP functionality is already integrated into the framework. Refer to this documentation to leverage this feature without needing to develop your own solution.


Nevertheless, if you were to create your custom solution, you can minimize the risk of name collisions by taking specific precautions to make your global names more unique. Here's an example illustrating how you can achieve this:

  1. Prefix your function name with underscores.
  2. Incorporate a random sequence of digits in the function name.
  3. Add a time stamp to further differentiate the function name.
  4. Clean up and remove the global after usage.

The provided code demonstrates these strategies in action.

// Using $window for Google async initializer requiring global function
angular.module('GoogleMapsInitializer')
    .factory('Initializer', function($window, $q){

        // Deferred object for maps loader
        var mapsDefer = $q.defer();

        // Google's asynchronous maps initialization URL expecting callback function
        var asyncUrl = 'https://maps.googleapis.com/maps/api/js?callback=';

        // Asynchronous loader function
        var asyncLoad = function(asyncUrl, callbackName) {
          var script = document.createElement('script');
          //script.type = 'text/javascript';
          script.src = asyncUrl + callbackName;
          document.body.appendChild(script);
        };

        // Generate a unique function name
        // Includes prefix, current time, and random number
        var fname = "__googleMapsInitialized_" + 
            (new Date().getTime()) + "_" + 
            (Math.random() + "").replace(".", "");

        // Callback function - resolves promise after successful map loading
        $window[fname] = function () {
            mapsDefer.resolve();
            // Remove the global variable once done
            delete $window[fname];
        };
        // Load Google Maps
        asyncLoad(asyncUrl, fname);

        return {

            // Usage: Initializer.mapsInitialized.then(callback)
            mapsInitialized : mapsDefer.promise
        };
    })

Check out a demonstration of the unique function name generator here: http://jsfiddle.net/jfriend00/oms7vc6o/

P.S. Although I'm not knowledgeable in Angular myself, it seems that Angular handles JSONP requests seamlessly, eliminating the need for creating your own solution. Refer to this Angular documentation page, as well as this related question and this informative article for in-depth insights.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Stop working to $(this) in jquery when clicking outside

I'm facing an issue with my code and would like some help. I have a button that toggles the visibility of a filter element, which is working fine. However, I now want to implement a "click outside" effect to close the filter when clicking on any body ...

Is there a way to divide my time during work hours using Javascript?

This is just a simple example. 9.00 - 18.00 I am looking to modify the schedule as follows: 9.00 - 10.00 10.00 - 11.00 11.00 - 12.00 12.00 - 13.00 13.00 - 14.00 14.00 - 15.00 15.00 - 16.00 16.00 - 17.00 17.00 - 18.00 The current code implementation see ...

Having trouble with Gulp hanging on the task named 'some_task_name' when using gulp.parallel or gulp.series?

Out of the blue, my gulp configuration suddenly stopped working. It gets stuck on 'Starting...' when I use tasks with gulp.parallel or gulp.series. Just yesterday, the same config was running smoothly. Why did this sudden change occur? Here is a ...

Creating personalized columns in a BootstrapVue table

I'm having an issue with the b-table component in bootstrap-vue. The array containing my items is structured like this: [{ id: 1, name: "Test", phone: 555-111-666, address: "Some Address", //etc... }] I have a couple of question ...

Choose the option from the jQuery dropdown list based on the displayed text instead of the value

In continuation of my previous question on jQuery getting values from multiple selects together, I am working with a select list like this: <select name="access" class="change" id="staff_off" runat="server"> <option value="8192">Off< ...

When using setState in the onRowSelection event with React's Material-ui tableRow, the selection cannot be properly controlled

Currently, I am working with a material-ui table https://i.stack.imgur.com/JIzLT.png and my goal is to pass selected rows to a function when the DELETE button is clicked. constructor(props) { super(props); this.state = { selecte ...

Record every action taken in the browser and compile it into a detailed HTML report

I am looking for a way to record and display all the browser actions performed in a test script in an HTML report. I am using protractor along with protractor-html-screenshot-reporter for reporting purposes. Is there any tool or API available that can he ...

Developing a system mode called "night mode"

I've decided to incorporate a dark mode feature into my Wordpress theme. Creating both dark and light modes was a breeze, but now I want to add a third mode that serves as the default for pages. This new mode will automatically switch between dark a ...

Using JSON to insert an array into an object with identical key name

var arr = ['1', '2', '3'] var part = {} var partContents = [] arr.map(function(i){ partContents.push({ obj: i }) part['text'] = partContents }) console.log(part); Is there a way to create separate arrays with ...

Simple steps to submit a user-entered value in AngularJS with basic validation and error handling

In an attempt to send user-entered input values to the Servlet, we encountered an issue. For instance, when a user enters a minimum length for an input field and the inbuilt angular validation triggers an error related to the minimum length, the correspon ...

Error TS2403: All variable declarations following the initial declaration must be of the same type in a React project

While developing my application using Reactjs, I encountered an error upon running it. The error message states: Subsequent variable declarations must have the same type. Variable 'WebGL2RenderingContext' must be of type '{ new (): WebGL2 ...

Error encountered when running NPM start - file path unable to locate JSON package file

Hello everyone, I'm new here and appreciate any help in advance! I'm currently working on my first project and encountering some challenges. The biggest one is that whenever I try to run npm start, I keep getting an error message: I've att ...

The content of xmlhttp.responseText is not being displayed in the innerHTML

As part of my ongoing effort to enhance my understanding of Ajax for work purposes, I have been following the W3Schools tutorial and experimenting with my Apache2 server. In this process, I have placed a file named ajax_info.txt on the server (in /var/www ...

Generating and Retrieving Dynamic URL with Jquery

My web page named single-colur.html has the ability to handle various query strings, such as: single-colour.html?id=1 single-colour.html?id=2 single-colour.html?id=3 single-colour.html?id=4 The parameter id in the URL corresponds to an entry in a table c ...

Utilizing Socket.io within secured routes

I'm currently working on a web application that involves user authorization and the ability to chat with others. I've encountered an issue where, despite including e.preventDefault() in my JavaScript code for the submit button, the page still ref ...

The modal disappears when the user clicks on the Previous/Next buttons of the jQuery UI datepicker

Using the jQuery datepicker from https://jqueryui.com/datepicker/ along with the UIkit framework found at I'm trying to incorporate the datepicker within a form that is inside a modal window. The issue arises when the modal window disappears after i ...

Inconsistencies observed during the native JSON import process in JavaScript

Encountered a strange behavior when loading a JSON file into JavaScript while working on a React project. Seeking an explanation and guidance on properly accessing data from the JSON data store. The JSON file contains product data: { "product ...

`The challenge of navigating within Material UI tabs in a React js project`

In my current project, I am utilizing React Js along with the Material UI Tabs component to switch between two different components. However, I have encountered an issue where when I navigate to Tab 2 or Tab 1 by clicking on them, the route changes and th ...

``When executing the `npm install` command, it does not install the sub-dependencies of a local package

I am facing an issue with my packages. One package named package-a has a dependency on another package called package-b which is not published on npm but resides in my file system. When I try to run npm install from the directory of package-a, the dependen ...

A JavaScript function that is only triggered half of the time

After browsing through various forums like StackOverflow, I couldn't find a solution that perfectly fits my issue. I may be new to programming, but I've managed to create several projects already. Currently, I am working on integrating them into ...