使用浏览器时如何公开谷歌地图的回调函数?



我正在使用Gulp和Browserify来捆绑我的JavaScript。我需要公开一个应在谷歌地图API加载后执行的回调函数。

如何在不使用类似window.initMap的情况下完成此操作?这样做的问题是我需要在 initMap 中触发大量其他方法,因此除了使用window.functionName和污染全局命名空间之外,还必须有更好的方法来做到这一点。

另一方面,是否可以仅排除callback参数并执行类似操作?

$.getScript('https://maps.googleapis.com/maps/api/js').done(function() {
initMap();
});

任何帮助将不胜感激。我花了更多的时间,我承认这是为了让它发挥作用。

gulpfile.js:

gulp.task('browserify', ['eslint'], function() {
return browserify('/src/js/main.js')
.bundle()
.pipe(source('main.js'))
.pipe(buffer())
.pipe(gulp.dest('/dist/js'))
.pipe(reload({ stream: true }));
});

主.js:

require('jquery');
require('./map');

地图.js:

var map = (function() {
'use strict';
var mapElement = $('#map');
function googleMapsAPI() {
$.getScript('https://maps.googleapis.com/maps/api/js?callback=initMap');
}
function initMap() {
var theMap = new google.maps.Map(mapElement);
// functions...
}
function init() {
googleMapsAPI();
}
});
map.init();

不,不包含callback参数是不行的。

谷歌地图API库调用一堆其他脚本加载到页面上,然后,当它们全部加载时,在窗口对象上调用callback参数。

只需在window对象上声明它:

var MyApp = {
init: function() {
//all your stuff
}
}
window.initMap = function() {
window.initMap = null; //set this to null this so that it can't get called anymore....if you want
MyApp.init();
};

然后只需在您的页面上添加脚本标记:

<script src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>

如果要加载脚本,然后在加载脚本后执行某些操作,则可以在注入script时设置属性asynconload。通过将所有代码包装到 IIFE 中,我们将保持私有IIFE中定义的所有对象,避免填充全局命名空间window。请参阅以下示例:

// IIFE (Immediately-Invoked Function Expression)
// Keeps all private
!function() {
/**
* Injects the script asynchronously.
*
* @param {String} url: the URL from where the script will be loaded
* @param {Function} callback: function executed after the script is loaded
*/
function inject(url, callback) {
var tag = 'script',
script = document.createElement(tag),
first = document.getElementsByTagName(tag)[0];
script.defer = script.async = 1; // true
script.type = 'text/javascript';
script.src = url;
script.onload = callback;
first.parentNode.insertBefore(script, first);
}
/**
* Injects and initializes the google maps api script.
*/
function injectMapsApi() {
var key = 'your-api-key';
var query = '?key=' + key;
var url = 'https://maps.googleapis.com/maps/api/js' + query;
inject(url, initMapsApi);
}
/**
* Callback that initializes the google maps api script.
*/
function initMapsApi() {
var maps = window.google.maps;
// ... code initializations
console.log(maps);
}
injectMapsApi();
}(); // end IIFE

您需要注册并声明您的API密钥才能使用谷歌地图API。更多信息在这里:

  • https://developers.google.com/maps/documentation/javascript/get-api-key
  • https://developers.google.com/maps/documentation/javascript/tutorial#Loading_the_Maps_API

老实说,我认为在这里简单地定义一个全局initMap函数以保持简单,同时利用Google地图异步初始化是一个更好的解决方案。这听起来像是一个黑客,但你可以为函数定义一个随机名称,然后在谷歌地图SDK调用它后将其从全局范围中删除。此机制类似于 JSONP 中使用的机制。

var functionName = getRandomName();
window[functionName] = function() {
window[functionName] = undefined;
// call to your initialization functions
};

在此答案中,您可以查看防止污染全局范围的方法是使Google地图脚本同步加载,这可能会损害用户体验,尤其是在智能手机上。

我对谷歌采取的这种方法也有问题。我自己不太喜欢它。

我最近处理这个问题的方法是创建全局函数,并触发一个事件来触发我的实际应用程序 javascript。这样,我就可以让我的应用程序 JS 摆脱处理地图 API 处理,并且它是我的主要对象之外的一个小全局函数调用。

function initMap(){
$(document).ready(function(){
$(window).on('GoogleMapsLoaded', myObj.init());
$(window).trigger('GoogleMapsLoaded');
});
};

这样,我只需在脚本 url 中包含callback=initMap

更新:另一种选择是仅将回调作为函数包含在对象中。例如:你的对象可能是这样的

var app = app || {};
(function($){
$(function(){
$.extend(app, {
initMap:function(yourMainWrapDiv){
//Do whatever you need to do after the map has loaded
},
mapLoadFunction(){
//Map API has loaded, run the init for my whole object
this.initMap($('#mainWrapper'))
},
mainInit: function(){
///do all your JS that can or needs  
// to be done before the map API loads
this.maybeSetSomeBindings();
},
maybeSetSomeBindings: function(){
//do things
}
});
//On document ready trigger your mainInit
//To do other things while maps API loads
app.mainInit()
});
})(jQuery);

然后,您可以使用回调跳转到一个全局对象中,并运行仅针对地图处理所需的运行内容。您的 API 网址可能与callback=app.initMap

这也可以保持它更干净

更新2:另一种选择(我进行了最低限度的测试(是不在Google API URL中使用callback参数,并将其与您需要的任何其他库链接。(地点、搜索等(。https://maps.googleapis.com/maps/api/js?key=YOUR-KEY-HERE&libraries=places例如。

然后在你的对象初始化函数中,只需设置一个计时器,看看google对象是否可用!也许是这样的:

var app = app || {};
(function($){
$(function(){
$.extend(app, {
init:function(){
var self = this;
var timer = setInterval(function(){
if ($('.ex').length){ //but really check for google object
console.log('things exist google, elements, etc..');
self.next();
clearInterval(timer);
}
});
},
next:function(){
console.log('google object exists')
}
});
app.init()
});
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='ex'>as an example for something to trigger a flag (true/false) to clear the interval</div>

在任何情况下,当您尝试访问全局对象时,在这种情况下app,作为 URL 中的回调,您将callback=app.yourFunctionToCallNOTcallback=app.funtionToCall()script标记还应具有归属于它的asyncdefer属性,以促进进一步的 HTML 解析(应用的 JS 应直接在 MAPS 脚本之后(

相关内容

  • 没有找到相关文章

最新更新