javascript - script - google maps html5
¿Cómo exponer la función de devolución de llamada para Google Maps al usar Browserify? (4)
Honestamente creo que aquí es una mejor solución simplemente definir una función global de initMap
para mantener las cosas simples mientras se aprovecha la inicialización asincrónica de Google Maps. Puede sonar como un hack, pero puede definir un nombre aleatorio para la función y luego simplemente eliminarlo del alcance global una vez que Google Maps SDK lo haya llamado. Este mecanismo es similar al utilizado en JSONP.
var functionName = getRandomName();
window[functionName] = function() {
window[functionName] = undefined;
// call to your initialization functions
};
En esta respuesta , puede comprobar que la forma de evitar la contaminación del alcance global es hacer que el script de google maps se cargue de forma sincronizada, lo que podría dañar la experiencia del usuario, especialmente en los teléfonos inteligentes.
Estoy usando Gulp y Browserify para agrupar mis JavaScripts. Necesito exponer una función de devolución de llamada que se debe ejecutar después de que se cargue la API de Google Maps.
¿Cómo se puede hacer esto sin usar algo como window.initMap
? El problema con esto es que necesito disparar una gran cantidad de otros métodos dentro de initMap, por lo que tiene que haber una forma mejor de hacerlo además de usar window.functionName
y contaminar el espacio de nombres global.
Por otro lado, ¿está bien simplemente excluir el parámetro de callback
y hacer algo como esto en su lugar?
$.getScript(''https://maps.googleapis.com/maps/api/js'').done(function() {
initMap();
});
Cualquier ayuda sería muy apreciada. He pasado más tiempo que nunca admitiría para hacer que esto funcione.
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();
Si desea cargar la secuencia de comandos y luego hacer algo cuando la secuencia de comandos se ha cargado, puede establecer los atributos async
y onload
al inyectar la script
. Envolviendo todo el código en un IIFE mantendremos privados todos los objetos definidos dentro del IIFE , evitando poblar la window
espacio de nombres global. Vea el siguiente ejemplo:
// 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
Debes registrarte y reclamar tu clave de API para usar la API de google maps. Más información aquí:
No, no está bien no incluir el parámetro de callback
.
La biblioteca de la API de google maps llama a un montón de otros scripts para cargar en la página y luego, cuando se han cargado todos, se llama al parámetro de callback
llamada en el objeto de la ventana.
Simplemente declararlo en el objeto 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();
};
y luego simplemente incluya la etiqueta de script en su página:
<script src="https://maps.googleapis.com/maps/api/js?callback=initMap"></script>
He tenido problemas con este enfoque que Google también ha tomado. No me gusta mucho yo mismo.
Mi forma de lidiar con esto últimamente ha sido crear la función global, con un giro de disparar un evento para activar mi aplicación javascript. De esta forma, tengo mi aplicación JS limpia de tratar el manejo de la API de mapas, y es una pequeña llamada de función global fuera de mi objeto principal.
function initMap(){
$(document).ready(function(){
$(window).on(''GoogleMapsLoaded'', myObj.init());
$(window).trigger(''GoogleMapsLoaded'');
});
};
Con eso solo callback=initMap
en la url del script.
ACTUALIZAR: Otra opción es simplemente incluir su devolución de llamada como una función dentro de su objeto. Ejemplo: su objeto podría ser algo así como
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);
Luego puede usar la devolución de llamada para saltar dentro de su único objeto global y ejecutar lo que necesita ejecutar solo para el manejo del mapa. Su URL de API podría estar con callback=app.initMap
Eso podría mantenerlo más limpio también
ACTUALIZACIÓN 2: Otra opción más (probada mínimamente) sería NO usar el parámetro de callback
en el URL de la API de Google, y vincularlo con cualquier otra cosa, en cuanto a la biblioteca, que necesita. (lugares, búsqueda, etc.). https://maps.googleapis.com/maps/api/js?key=YOUR-KEY-HERE&libraries=places
por ejemplo.
Luego, en la función init de su objeto, simplemente configure un temporizador para ver si el objeto google
está disponible. Tal vez algo como esto:
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>
en cualquier caso, cuando intente acceder al objeto global, en este caso app
, como una devolución de llamada en la URL que establecerá callback=app.yourFunctionToCall
NOT callback=app.funtionToCall()
, la etiqueta de script
también debería tener los atributos async
y defer
se le atribuye para promover más análisis html (el js de su aplicación debe estar directamente después del script de mapas)