TypeError: window.initMap is not a function

2019-01-10 22:20发布

问题:

I am following this tutorial, basically copy all the code

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

but got an error saying that the initMap function is not a function. I am using angularjs in my project, could that be causing problems?

I copied the same code into plunker and it works just fine... What are the possible issues?

回答1:

Actually the error is being generated by the initMap in the Google's api script

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

so basically when the Google Map API is loaded then the initMap function is executed. If you don't have an initMap function, then the initMap is not a function error is generated.

So basically what you have to do is one of the following options:

  1. to create an initMap function
  2. replace the callback function with one of your own that created for the same purpose but named it something else
  3. replace the &callback=angular.noop if you just want an empty function() (only if you use angular)


回答2:

My explanation of this problem:

The .....&callback=initMap" async defer></script> makes that script load async (in parallel with DOM) and after load - execute initMap function. NOTICE that initMap() in global scope! We can't declare our initMap() after google's script because it should already be at the moment of finish async load. Although we can't load our script before this, because we need google's function to execute ours. This is like vicious circle.

Three solutions:

1'st and worst: make google's script load synchronously

  1. remove async defer
  2. remove &callback=initMap in src attribute
  3. put <script tag with your code after google's script

2'nd and best: just do this =)

  1. leave .....&callback=initMap" async defer></script> as is
  2. and put google's <script tag after your script
  3. write in your 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...
      }
    })
    

    this allow you load google's script async and run yours just after that

3'rd and strange: it will work... some times =)

  1. do same but simply write in global scope

    function initMap() {
      // your code
    }
    

    and if you write it in global scope, that will work regardless of what which code loads faster, your (sync) or google's (async). More often your wins



回答3:

I have been struggling for several days with this very popular in the last few months issue - "initMap is not a function".

Those two threads helped me:

  1. How to make a callback to Google Maps init in separate files of a web app

  2. Defer attribute doesn't work with Google Maps API?

Why does the map open sometimes and sometimes not. It depends on several factors like speed of connection, environment, etc. Because the initialization function sometimes runs after the google maps API kicks in, that's why the map is not displayed and the browser console throws an error. For me removing only the async attribute fixed the issue. The defer attribute stays.

If async is present: The script is executed asynchronously with the rest of the page (the script will be executed while the page continues the parsing) If async is not present and defer is present: The script is executed when the page has finished parsing If neither async or defer is present: The script is fetched and executed immediately, before the browser continues parsing the page Source - http://www.w3schools.com/tags/att_script_defer.asp

Hope that helps. Cheers.



回答4:

Removing =initMap worked for me:

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


回答5:

The problem has to do with the async attribute in the script tag. The Callback Function is trying to call "initMap()" when it doesn't really exists by the time the request finished.

To solve this I placed the Goole Maps Api Script bellow the script where my initMap function was declared.

Hope this helps



回答6:

This may seem obvious but just in case: If someone placed the JS code inside $(document).ready like this:

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

Then that's the problem because using async defer when loading the Google Maps API library, it will load asynchronously, and when it finishes loading, will look for the callback function, which needs to be available by then.

So, you just need to put the code outside $(document).ready, and:

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

at the very bottom, so your page loads FAST :-)



回答7:

Solved by adding

<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>

At the beginning of the same file which contains the rest of the code with function initMap(). It's definitely not the best solution, but it works..

But I think that if you would transform function initMap() to something like var=initMap() and then $(function () ... it would work too.



回答8:

I am using React and I had mentioned &callback=initMap in the script as below

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

then is just removed the &callback=initMap part now there is no such error as window.initMap is not a function in the console.



回答9:

Put this in your html body (taken from the official angular.js website):

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

I believe that you were using some older angular.js files since you don't have any issues in plunker and therefore you got the specified error.



回答10:

turns out it has to do with ng-Route and the order of loading script wrote a directive and put the API script on top of everything works.



回答11:

Create initMap method between "" tag or load javascript file before call 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>



回答12:

Could be your initMap function is in a $(document).ready function. If it is then it won't work, it has to be outside of any other functions.



回答13:

In addition to @DB.Null's answer, I used Function.prototype as no-op (no-operation) function on #3 instead of angular.noop (I don't have angular in my project).

So this...

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



回答14:

In my case there was a formatting issue earlier on, so the error was a consequence of something else. My server was rendering the lat/lon values with commas instead of periods, because of different regional settings.



回答15:

In my case I solved it like this:

function initMap() {
    if($('#map').length > 0) {
        // your code
    }
}


回答16:

your call back method probably is not globally accessible. in my case I'd used transpoiled ES6 codes via webpack which caused my callback method not being global anymore.

Try to attach your callback method explicitly to window like so right after your callback method declaration and see the result

window.initMap = initMap;

it worked for me.