2017-08-10 77 views
6

我正在使用Gulp和Browserify捆绑我的JavaScript。我需要公开一个应该在Google Maps API加载后执行的回调函数。如何在使用Browserify时公开Goog​​le地图的回调函数?

如何在不使用类似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 })); 
}); 

main.js:

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

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(); 

回答

3

不,不包括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> 
+0

问题在于'initMap()'被触发后,我需要调用各种其他自定义函数。如果我用'map.functionName()'调用它们,我得到一个函数未定义的错误。唯一的解决方法是使用'window.functionName()',但是会污染全局名称空间。 – Cofey

+1

@Cofey - 你别无选择,只能*污染全局名称空间*,因为这是Google地图可以使用'callback'的唯一方式。许多人认为“从来没有把任何东西放在全球范围内,因为这样做很糟糕,但这是错误的。你应该考虑的是“不要在全球范围内放置任何你不需要在那里的东西。”您需要**由'callback = initMap'(即'initMap')定义的函数位于全局名称空间中。不要冒汗。 – Adam

+0

此外,当我开发客户端时,我通常会定义自己的名称,以便我可以*挂上东西*。我经常有'window.myNameSpace = window.myNameSpace || {}'在我的项目中,然后像window.myNameSpace.constants = {CONSTANT_ONE = 123456}那样挂掉'window.myNameSpace'的各种东西' – Adam

0

老实说,我认为这是一个更好的解决方案,简单地定义一个全球initMap功能可以让事情变得简单,同时利用Google Maps异步初始化。这可能听起来像是黑客,但您可以为该函数定义一个随机名称,然后只要Google Maps SDK调用该名称,就可以将其从全局范围中移除。这种机制与JSONP中使用的机制类似。

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

this answer你可以检查出的办法,以防止污染全局范围是使谷歌地图脚本负荷同步,有什么会伤害用户体验,特别是在智能手机上。

1

如果要加载脚本,然后在做一些事情脚本已被加载,您可以在注入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密钥才能使用Google Maps API。点击此处了解详情:

+0

我真的很感谢你带来了IIFE选项,因为我的就职项目模板使用了一个IIFE,并且我试图弄清楚如何做到这一点。很多我不完全理解。在你的'inject'函数中,你能指向一个我能读懂的资源吗?这个资源解释了设计以及你用这个函数完成了什么? –

+0

@ tim.rohrer函数'inject()'创建一个HTML元素'

相关问题