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

标签 javascript jquery ajax json google-maps

我写了一个小脚本,它从 JSON 文件加载 Google map 标记并将它们放在 map 上。该脚本应该能够处理多个实例。目前脚本看起来像这样(为了测试我使用了 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() 函数被连续调用两次,我在 .loadAPI 中检查() 如果 Google Maps API 已经加载失败(Chrome Inspector:Uncaught TypeError:Object # has no method 'Load'(Google Maps API JS 文件))。

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

提前致谢。

最佳答案

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

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

关于javascript - 使用 AJAX 加载 Google Maps API...但多个实例仅加载一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22019382/

相关文章:

javascript - 如何使用 Jest 在 typescript 中模拟 Date 对象?

javascript - 纯 JS 或 Lodash - 用其他对象的值替换对象值

javascript - HTML CSS - 单击时使图标改变颜色(如链接)

javascript - jQuery/Javascript - 在元素获得焦点时执行操作

php - 通过ajax检索php处理过的数据

c# - Ajax 传递空值但 Controller 在 ASP.NET MVC 中获取 null

jquery - 在触发控制下显示的下拉菜单

javascript - 在 DATETIMEPICKER javascript 中禁用 future 7 天

javascript - 为什么不使用!对于 MS AJAX 中的 bool 值?

javascript - 获取/查找 URL 字符串组件 IF 字符串组件存在