【问题标题】:Load Google Maps API with AJAX... but only once for multiple instances使用 AJAX 加载 Google Maps API ......但对于多个实例只加载一次
【发布时间】:2014-02-25 15:52:18
【问题描述】:

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

<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>

如果我只有.init() 一个这样的实例,它就可以工作:

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

但是一旦我尝试多个实例,它就会失败:

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

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

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

提前致谢。

【问题讨论】:

    标签: javascript jquery ajax json google-maps


    【解决方案1】:

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

    1. 因为您每次都调用 googleMaps() 函数,所以您正在创建一个对象的新实例,该实例跟踪 google maps api 何时/是否已加载。您需要在 googleMaps 函数之外提取加载 api 的部分(或使用共享变量)。
    2. 即使您保持 loadAPI 函数原样,您仍然可能会遇到竞争条件,即加载 google 地图库的 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);
            };
    

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

    【讨论】:

      猜你喜欢
      • 2011-09-15
      • 2011-07-14
      • 2012-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多