使用AJAX加载Google Maps API ...但对于多个实例仅加载一次

时间:2021-11-21 19:52:23

I wrote a little script, which loads Google Maps markers from a JSON file and puts them on a map. The script should be able to handle multiple instances. At the moment the script looks like this (for testing i used this JSON file):

我写了一个小脚本,它从JSON文件中加载Google Maps标记并将它们放在地图上。该脚本应该能够处理多个实例。目前脚本看起来像这样(测试我使用这个JSON文件):

<div id="map" data-file="test.json" style="width: 200px; height: 200px; "></div>
<div id="map2" data-file="test2.json" style="width: 200px; height: 200px; "></div>
<!-- JAVASCRIPT -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script>
    $(function() {
        var googleMaps = function() {
            var $el,
                apiLoaded = false;


            // Init
            // @public
            function init(el) {
                $el = $(el);

                loadData($el.data('file'));
            };


            // Creating a marker and putting it on the map
            // @private
            function createMarker(data) {
                var marker = new google.maps.Marker({
                    position: new google.maps.LatLng(data.lat, data.lng),
                    map: map,
                    title: data.title
                });
            }


            // JSON file and API loaded
            // @private
            function ready(data) {
                // Basic settings
                var mapOptions = {
                    center: new google.maps.LatLng(58, 16),
                    zoom: 7,
                    mapTypeId: google.maps.MapTypeId.ROADMAP
                };
                map = new google.maps.Map($el[0], mapOptions);

                // Create markers
                $.each(data, function(key, value) {
                    createMarker(value);
                });
            }


            // Load API
            // @private
            function loadAPI(callback) {
                if (typeof google === 'object' && typeof google.maps === 'object') {
                    // API was already loaded
                    if(typeof(callback) === 'function') {
                        callback();
                    }
                } else {
                    // API wasn't loaded yet
                    // Send an AJAX request
                    $.ajax({
                        url: 'http://www.google.com/jsapi/',
                        dataType: "script",
                        success: function() {
                            google.load('maps', '3', {
                                callback: function() {
                                    // Check if callback function is set
                                    if(typeof(callback) === 'function') {
                                        callback();
                                    }
                                }, 
                                other_params: 'sensor=false'
                            });
                        }
                    });
                }
            };


            // Load JSON file
            // @private
            function loadData(file) {
                $.ajax({
                    url: file,
                    success: function(data) {
                        var parsedJson = $.parseJSON(data);
                        loadAPI(function() {
                            ready(parsedJson);
                        });
                    },
                    error: function(request, status, error) {
                        // Error
                        console.log(error);
                    }
                });
            };

            return {
                init: init
            }
        }           
    });
</script>

It works if i only .init() one instance like so:

如果我只有.init()这样的一个实例,它是有效的:

googleMaps().init(document.getElementById('map'));

But it fails as soon as i try multiple instances:

但是当我尝试多个实例时它就会失败:

googleMaps().init(document.getElementById('map'));
googleMaps().init(document.getElementById('map2'));

I think it fails because the .loadAPI() and google.load() function are getting called twice in a row and my check inside .loadAPI() if the Google Maps API was already loaded fails (Chrome Inspector: Uncaught TypeError: Object # has no method 'Load' (Google Maps API JS file) ).

我认为它失败了,因为.loadAPI()和google.load()函数连续两次被调用,如果已经加载了Google Maps API,我的.loadAPI()内部检查失败(Chrome Inspector:Uncaught TypeError:Object#没有方法'加载'(谷歌地图API JS文件))。

How do i make sure that my AJAX request inside the .loadAPI() function doesn't get called twice? I could use a global variable outside my Module Pattern, which i set to true, but i don't really want to use one for that purpose. Is there anything other i could use?

我如何确保.loadAPI()函数内的AJAX请求不会被调用两次?我可以在我的模块模式之外使用一个全局变量,我设置为true,但我真的不想为此目的使用一个。还有其他我可以使用的吗?

Thanks in advance.

提前致谢。

1 个解决方案

#1


5  

There are two separate issues that can occur here.

这里可能会出现两个不同的问题。

  1. Because you are calling the googleMaps() function each time, you are creating a new instance of the object which tracks when/if the google maps api has loaded. You need to extract the part that loads the api outside of the googleMaps function (or use a shared variable).
  2. 因为您每次都在调用googleMaps()函数,所以您正在创建一个新的对象实例,用于跟踪google maps api何时加载。您需要提取在googleMaps函数之外加载api的部分(或使用共享变量)。
  3. Even if you kept the loadAPI function as is you can still encounter a race condition where the ajax request to load the google maps library can be fired off twice. The reason why you are seeing that error is that when you check in loadAPI if the google object is available, it hasn't actually been set up yet by the first ajax request.
  4. 即使您保持loadAPI功能,您仍然可能遇到竞争条件,其中加载谷歌地图库的ajax请求可以被触发两次。您看到该错误的原因是,当您检查loadAPI时,如果Google对象可用,则第一个ajax请求实际上尚未设置它。

You can use the Promise API to deal with issues like this. I changed the loadAPI method to use a promise, and like I said, it needs to be moved outside of the googleMaps function

您可以使用Promise API来处理这样的问题。我更改了loadAPI方法以使用promise,就像我说的那样,它需要移到googleMaps函数之外

        var loadAPIPromise;
        // Load API
        function loadAPI(callback) {
            if (!loadAPIPromise) {
                var deferred = $.Deferred();
                $.ajax({
                    url: 'http://www.google.com/jsapi/',
                    dataType: "script",
                    success: function() {
                        google.load('maps', '3', {
                            callback: function() {
                                deferred.resolve();
                            }, 
                            other_params: 'sensor=false'
                        });
                    }
                });
                loadAPIPromise = deferred.promise();
            }
            loadAPIPromise.done(callback);
        };

Here is a jsfiddle example http://jsfiddle.net/callado4/gA79R/4/

这是一个jsfiddle示例http://jsfiddle.net/callado4/gA79R/4/

#1


5  

There are two separate issues that can occur here.

这里可能会出现两个不同的问题。

  1. Because you are calling the googleMaps() function each time, you are creating a new instance of the object which tracks when/if the google maps api has loaded. You need to extract the part that loads the api outside of the googleMaps function (or use a shared variable).
  2. 因为您每次都在调用googleMaps()函数,所以您正在创建一个新的对象实例,用于跟踪google maps api何时加载。您需要提取在googleMaps函数之外加载api的部分(或使用共享变量)。
  3. Even if you kept the loadAPI function as is you can still encounter a race condition where the ajax request to load the google maps library can be fired off twice. The reason why you are seeing that error is that when you check in loadAPI if the google object is available, it hasn't actually been set up yet by the first ajax request.
  4. 即使您保持loadAPI功能,您仍然可能遇到竞争条件,其中加载谷歌地图库的ajax请求可以被触发两次。您看到该错误的原因是,当您检查loadAPI时,如果Google对象可用,则第一个ajax请求实际上尚未设置它。

You can use the Promise API to deal with issues like this. I changed the loadAPI method to use a promise, and like I said, it needs to be moved outside of the googleMaps function

您可以使用Promise API来处理这样的问题。我更改了loadAPI方法以使用promise,就像我说的那样,它需要移到googleMaps函数之外

        var loadAPIPromise;
        // Load API
        function loadAPI(callback) {
            if (!loadAPIPromise) {
                var deferred = $.Deferred();
                $.ajax({
                    url: 'http://www.google.com/jsapi/',
                    dataType: "script",
                    success: function() {
                        google.load('maps', '3', {
                            callback: function() {
                                deferred.resolve();
                            }, 
                            other_params: 'sensor=false'
                        });
                    }
                });
                loadAPIPromise = deferred.promise();
            }
            loadAPIPromise.done(callback);
        };

Here is a jsfiddle example http://jsfiddle.net/callado4/gA79R/4/

这是一个jsfiddle示例http://jsfiddle.net/callado4/gA79R/4/