web-dev-qa-db-fra.com

TypeError: window.initMap n'est pas une fonction

Je suis ce tutoriel, en gros copier tout le code

https://developers.google.com/maps/documentation/javascript/tutorial

mais j'ai eu une erreur en disant que la fonction initMap n'est pas une fonction . J'utilise angularjs dans mon projet, cela pourrait-il causer des problèmes?

J'ai copié le même code dans Plunker et cela fonctionne très bien .... Quels sont les problèmes possibles? 

46
user2901633

s’avère que cela a à voir avec ng-Route et l’ordre de chargement du script a écrit une directive et placé le script API au-dessus de tout ce qui fonctionne.

1
user2901633

En réalité, l'erreur est générée par initMap dans le script d'api de Google.

 <script async defer
  src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap">
</script>

donc, lorsque l’API Google Map est chargé, la fonction initMap est exécutée. Si vous n'avez pas de fonction initMap, alors initMap n'est pas une erreur de fonction générée.

Donc, en gros, vous devez choisir l’une des options suivantes:

  1. créer une fonction initMap
  2. remplace la fonction de rappel par l'une des vôtres créée dans le même but mais nommée autrement
  3. remplacez le &callback=angular.noop si vous voulez juste une fonction vide () (seulement si vous utilisez angular)
53
DB.Null

Mon explication de ce problème:

Le .....&callback=initMap" async defer></script> fait que le script se charge async (en parallèle avec DOM) et après le chargement - exécute la fonction initMap. AVIS qu'initMap () dans la portée globale! Nous ne pouvons pas déclarer notre script initMap () après google car il devrait déjà être au moment de son chargement asynchrone. Bien que nous ne puissions pas charger notre script avant ceci, car nous avons besoin de la fonction de Google pour exécuter la nôtre. C'est comme un cercle vicieux.

Trois solutions:

Le premier et le pire: faire en sorte que le script de Google se charge de manière synchrone

  1. supprimer async defer
  2. supprimer &callback=initMap dans l'attribut src
  3. placez la balise <script avec votre code après le script de Google

2ème et meilleur: faites ceci =)

  1. laisser .....&callback=initMap" async defer></script> tel quel
  2. et mettez la balise <script de Google après votre script
  3. écris dans ton script 

    function initMap() {} // now it IS a function and it is in global
    
    $(() => {
      initMap = function() {
        // your code like...
        var map = new google.maps.Map(document.getElementById('map'), {/*your code*/});
        // and other stuff...
      }
    })
    

    cela vous permet charger le script async de Google et exécuter le vôtre juste après 

3ème et étrange: ça va marcher ... quelques fois =)

  1. faire la même chose mais simplement écrire en champ d'application global

    function initMap() {
      // your code
    }
    

    et si vous l'écrivez dans une portée globale, cela fonctionnera quel que soit le code , qui se charge plus rapidement, votre (sync) ou celui de Google (async). Plus souvent tes victoires

28
Andrey Kudriavtsev

Cela fait plusieurs jours que je me bats avec ce numéro très populaire de ces derniers mois: "initMap n'est pas une fonction".

Ces deux fils m'ont aidé:

  1. Comment rappeler un initiateur Google Maps dans des fichiers distincts d'une application Web

  2. L'attribut de report ne fonctionne pas avec l'API Google Maps?

Pourquoi la carte est ouverte parfois et parfois pas. Cela dépend de plusieurs facteurs, tels que la vitesse de connexion, l'environnement, etc. Comme la fonction d'initialisation s'exécute parfois après le démarrage de l'API Google Maps, la carte ne s'affiche pas et la console du navigateur génère une erreur. Pour moi, supprimer uniquement l'attribut async a résolu le problème. L'attribut différer reste.

Si async est présent: le script est exécuté de manière asynchrone avec le reste de la page (le script sera exécuté tant que la page poursuivra l'analyse) Si async n'est ni présent ni différé: le script est exécuté lorsque la page est en cours analyse terminée Si ni asynchrone ni différé n'est présent: le script est extrait et exécuté immédiatement, avant que le navigateur ne continue d'analyser la page Source - http://www.w3schools.com/tags/att_script_defer.asp

J'espère que cela pourra aider. À votre santé.

9
Viktor Georgiev

Supprimer =initMap a fonctionné pour moi:

<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback"></script>
8
Tom

Le problème concerne l'attribut async dans la balise de script. La fonction de rappel tente d'appeler "initMap ()" alors qu'elle n'existe pas encore à la fin de la demande.

Pour résoudre ce problème, j'ai placé le script Apole de Goole Maps sous le script où ma fonction initMap a été déclarée.

J'espère que cela t'aides

7
krlozadan

Cela peut sembler évident, mais juste au cas où: Si quelqu'un a placé le code JS dans $ (document) .ready comme ceci:

     $(document).ready(function() {
       ... Google Maps JS code ...
      }

C’est le problème car en utilisant asyncdefer lors du chargement de la bibliothèque d’API Google Maps, celle-ci se chargera de manière asynchrone et, une fois le chargement terminé, il recherchera la fonction de rappel, qui doit être disponible à cette date.

Donc, il suffit de mettre le code outside $ (document) .ready , et: 

<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initMap"
    async defer></script>

tout en bas, votre page se charge rapidement :-)

5
Hugo

Résolu en ajoutant 

<script async defer
    src="https://maps.googleapis.com/maps/api/js?key=XXXXXXX&callback=initMap">
    <!--
        https://developers.google.com/maps/documentation/javascript/examples/map-geolocation
    -->
</script>

Au début du même fichier qui contient le reste du code avec function initMap(). Ce n'est certainement pas la meilleure solution, mais ça marche ..

Mais je pense que si vous transformiez function initMap() en quelque chose comme var=initMap() puis $(function () ..., cela fonctionnerait aussi.

3
vohratom

J'utilise React et j'avais mentionné & callback = initMap dans le script ci-dessous 

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

ensuite, la partie &callback=initMap est simplement supprimée. Il n'y a plus d'erreur telle que window.initMap n'est pas une fonction de la console.

3
Samkit Shah

Créez une méthode initMap entre les balises "" ou chargez un fichier javascript avant d'appeler google api.

<script src="Scripts/main.js"></script>

<script src="https://maps.googleapis.com/maps/api/js?key=abcde&libraries=places&callback=initMap" async defer></script>

2

Mettez ceci dans votre corps html (tiré du site officiel angular.js):

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>

Je crois que vous utilisiez des fichiers plus anciens angular.js puisque vous n’avez aucun problème avec Plunker et que vous obtenez donc l’erreur spécifiée.

1
eugen sunic

votre méthode de rappel n'est probablement pas accessible globalement. Dans mon cas, j'avais utilisé des codes ES6 transpilés via Webpack, ce qui faisait que ma méthode de rappel n'était plus globale.

Essayez d’attacher explicitement votre méthode de rappel à window comme après la déclaration de la méthode de rappel et de voir le résultat 

window.initMap = initMap;

cela a fonctionné pour moi.

0
Code_Worm

En plus de la réponse de @ DB.Null, j'ai utilisé Function.prototype comme fonction no-op (aucune opération) sur # 3 au lieu de angular.noop (mon projet n'est pas angulaire.).

Donc ça...

<script async defer src="https://maps.googleapis.com/maps/api/js?key=API_KEY_HERE&callback=Function.prototype" type="text/javascript"></script>

0
Christopher Regner

Dans mon cas, il y avait un problème de formatage plus tôt, donc l'erreur était la conséquence de quelque chose d'autre. Mon serveur rendait les valeurs lat/lon avec des virgules au lieu de points, en raison de paramètres régionaux différents.

0
Savage

Peut-être que votre fonction initMap est dans une fonction $ (document) .ready. Si c'est le cas, cela ne fonctionnera pas, il devra être en dehors de toute autre fonction.

0
KNey