web-dev-qa-db-ja.com

TypeError:window.initMapは関数ではありません

私はこのチュートリアルに従っています、基本的にすべてのコードをコピーします

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

ただし、initMap関数は関数ではないというエラーが発生しました。私は私のプロジェクトでangularjsを使用していますが、それが問題を引き起こしているのでしょうか?

同じコードをplunkerにコピーしましたが、問題なく動作します...考えられる問題は何ですか?

51
user2901633

ng-Routeと関係があり、スクリプトをロードする順序がディレクティブを作成し、APIスクリプトをすべての機能の上に配置することが判明しました。

1
user2901633

実際には、エラーはGoogleのAPIスクリプトのinitMapによって生成されています

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

基本的に、Google Map APIがロードされると、initMap関数が実行されます。 initMap関数がない場合、initMapは関数ではありませんエラーが生成されます。

したがって、基本的にあなたがしなければならないことは、次のオプションのいずれかです。

  1. initMap関数を作成するには
  2. コールバック関数を、同じ目的で作成されたが別の名前を付けた独自の関数に置き換えます
  3. 空のfunction()のみが必要な場合は&callback=angular.noopを置き換えます(角度を使用する場合のみ)
55
DB.Null

この問題の私の説明:

.....&callback=initMap" async defer></script>は、そのスクリプトを(DOMと並行して)非同期にロードし、ロード後にinitMap関数を実行します。 グローバルスコープのinitMap()に注意してください! initMap()を宣言することはできませんafterGoogleのスクリプトは、非同期ロードの終了時点で既にあるはずです。スクリプトをロードすることはできませんがbeforeこれは、Googleの関数を実行する必要があるためです。これは悪循環のようなものです。

3つのソリューション:

1番目と最悪:Googleのスクリプトを同期的にロードする

  1. async deferを削除します
  2. src属性の&callback=initMapを削除します
  3. googleのスクリプトの後に、コードに<scriptタグを付けます

2番目と最高:ちょうどこれを行う=)

  1. .....&callback=initMap" async defer></script>をそのままにします
  2. スクリプトの後にGoogleの<scriptタグを配置します
  3. スクリプトを書く

    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...
      }
    })
    

    これにより、loadgoogleのスクリプト非同期と、その直後のrunが可能になります

3番目の奇妙な:それは動作します...何度か=)

  1. 同じことをしますが、単にグローバルスコープで記述します

    function initMap() {
      // your code
    }
    

    グローバルスコープで記述した場合、どのコードがより高速にロードされるか(あなたの(同期)またはGoogleの(非同期))に関係なく機能します。より頻繁にあなたの勝利

30

ここ数ヶ月で非常に人気のある「initMapは機能ではない」という問題に数日間苦労しています。

これらの2つのスレッドは私を助けてくれました。

  1. Webアプリの個別のファイルでGoogleマップの初期化にコールバックを行う方法

  2. Defer属性はGoogle Maps APIでは機能しませんか?

マップが開かれる場合と開かれない場合があります。接続速度、環境などのいくつかの要因に依存します。GoogleMaps APIの起動後に初期化関数が実行されることがあるため、マップが表示されず、ブラウザーコンソールがエラーをスローします。私にとっては、非同期属性のみを削除すると問題が修正されました。 defer属性はそのままです。

非同期が存在する場合:スクリプトはページの残りの部分と非同期で実行されます(スクリプトはページが解析を続行している間に実行されます)非同期が存在せず、延期が存在する場合:スクリプトはページの解析が終了したときに実行されます非同期も遅延もありません:ブラウザがページの解析を続ける前に、スクリプトがすぐにフェッチされて実行されますSource- http://www.w3schools.com/tags/att_script_defer.asp

お役に立てば幸いです。乾杯。

9
Viktor Georgiev

=initMapを削除するとうまくいきました:

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

この問題は、scriptタグのasync属性に関係しています。コールバック関数は、リクエストが終了するまでに実際には存在しないときに「initMap()」を呼び出そうとしています。

これを解決するために、initMap関数が宣言されたスクリプトの下にGoole Maps APIスクリプトを配置しました。

お役に立てれば

8
krlozadan

これは明らかなように思えるかもしれませんが、念のために:誰かが次のように$(document).ready内にJSコードを配置した場合:

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

それは問題です。GoogleMaps APIライブラリをロードするときにasyncdeferを使用すると、非同期にロードされ、ロードが完了するとコールバック関数が検索されます。

そのため、コードをoutside$(document).readyに追加するだけです。

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

一番下にあるので、ページは高速でロードされます:-)

6
Hugo

追加することで解決

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

function initMap()を含む残りのコードを含む同じファイルの先頭。それは間違いなく最良の解決策ではありませんが、機能します。

しかし、function initMap()var=initMap()のようなものに変換してから、$(function () ...のように変換すると、それも機能すると思います。

3
vohratom

私はReactを使用していますが、以下のようにスクリプトで&callback = initMapについて言及しました

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

その後、&callback=initMap部分が削除されるだけで、window.initMapはコンソールの関数ではないため、このようなエラーは発生しません。

3
Samkit Shah

「」タグの間にinitMapメソッドを作成するか、Google APIを呼び出す前にJavaScriptファイルをロードします。

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

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

これをhtml本文に入れます(angular.jsの公式Webサイトから取得)。

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

Plunkerに問題はなく、指定されたエラーが発生したため、古いangle.jsファイルを使用していたと思います。

1
eugen sunic

あなたのコールバックメソッドはおそらくグローバルにアクセス可能ではありません。私の場合、webpackを介してトランスポイルされたES6コードを使用していたため、コールバックメソッドがグローバルではなくなりました。

コールバックメソッド宣言の直後に、コールバックメソッドをwindowに明示的にアタッチして、結果を確認してください。

window.initMap = initMap;

それは私のために働いた。

0
Code_Worm

@ DB.Nullの答えに加えて、私はFunction.prototypeの代わりに#3でノーオペレーション(ノーオペレーション)関数としてangular.noopを使用しました(プロジェクトにangularがありません)。

したがって、この...

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

0

私の場合、以前にフォーマットの問題があったため、エラーは他の何かの結果でした。私のサーバーは、地域の設定が異なるため、ピリオドではなくコンマを使用して緯度/経度の値をレンダリングしていました。

0
Savage

InitMap関数が$(document).ready関数にある可能性があります。その場合、それは動作しません、それは他の機能の外にある必要があります。

0
KNey