可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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:
- to create an initMap function
- replace the callback function with one of your own that created for the same purpose but named it something else
- 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
- remove
async defer
- remove
&callback=initMap
in src
attribute
- put
<script
tag with your code after google's script
2'nd and best: just do this =)
- leave
.....&callback=initMap" async defer></script>
as is
- and put google's
<script
tag after your script
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 =)
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:
How to make a callback to Google Maps init in separate files of a web app
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.