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

Dan*_*iel 3 javascript ajax jquery json google-maps

我写了一个小脚本,它从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>
Run Code Online (Sandbox Code Playgroud)

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

googleMaps().init(document.getElementById('map'));
Run Code Online (Sandbox Code Playgroud)

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

googleMaps().init(document.getElementById('map'));
googleMaps().init(document.getElementById('map2'));
Run Code Online (Sandbox Code Playgroud)

我认为它失败了,因为连续两次调用.loadAPI()google.load()函数,.loadAPI()如果Google Maps API已经加载失败,我在里面检查(Chrome Inspector:Uncaught TypeError:Object#没有方法'Load'(Google Maps API JS文件) ).

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

提前致谢.

Jos*_*seM 5

这里可以发生两个不同的问题.

  1. 因为你每次调用谷歌地图()函数,您创建当/如果谷歌地图API的加载跟踪对象的新实例.您需要提取在googleMaps函数之外加载api的部分(或使用共享变量).
  2. 即使你不停的loadAPI功能是你仍然可以遇到的竞争条件要加载谷歌地图图书馆Ajax请求可进行两次发射了.您看到该错误的原因是,当您检查loadAPI时,如果Google对象可用,则第一个ajax请求实际上尚未设置它.

您可以使用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);
        };
Run Code Online (Sandbox Code Playgroud)

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