如何在加载google.maps.OverlayView派生类之前等待google地图API加载完成

13

我有一个独立的label.js文件,在其中定义了一个自定义的覆盖物。它使用了google.maps.OverlayView作为它的原型:

Label.prototype = new google.maps.OverlayView();

我不确定在我的index.html文件中应该在哪里放置这个js文件的脚本标签。如果我像下面这样把脚本标签放在google地图加载标签下面:

....
        <script async defer
            src="https://maps.googleapis.com/maps/api/js?...
        </script>
        <script src="js/label.js"></script>
    </body>
</html>

当地图API尚未加载导致错误时,label.js文件会立即加载。

我目前通过在我的地图加载回调中手动加载JS来解决这个问题:

function initMap() {
    gMap = new google.maps.Map(document.getElementById(strMapDivName), {
        center: {lat: 21, lng: 78},
        mapTypeId: google.maps.MapTypeId.HYBRID,
        zoom: 6,
        heading: 90,
        tilt: 0
    });

    // Load label.js afterwards so we can be sure that the google maps api has loaded
    var fileref=document.createElement('script')
    fileref.setAttribute("type","text/javascript")
    fileref.setAttribute("src", "js/label.js")

    document.getElementsByTagName("head")[0].appendChild(fileref)

}

这是解决这个问题的最佳方法吗?


4
当您异步加载地图API时,我会说这是最佳方式。 - Dr.Molle
6个回答

6

在API调用中应该包含一个回调函数。

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

你可以在回调函数中包含任何与地图相关的代码:
function myFunction() {
  // Your code here
}

如果您需要等待地图“准备就绪”,即在地图选项和“空闲”状态下显示地图,您可以使用:

google.maps.event.addListenerOnce(map, 'idle', function () {
    // map is ready
});

但你仍然应该在回调函数中包含这个。


6

我知道现在有些晚了,但我使用了下面这段代码

var mapWaitCount = 0;
var mapWaitMax = 5;

function map_load(param1, param2, ...) { // if you need any param
    mapWaitCount++;
    // if api is loaded
    if(typeof google != 'undefined') {
        // your code here 
    }
    // try again if until maximum allowed attempt
    else if(mapWaitCount < mapWaitMax) {
        console.log('Waiting attempt #' + mapWaitCount); // just log
        setTimeout(function() { map_load(); }, 1000);
    }
    // if failed after maximum attempt, not mandatory
    else if(mapWaitCount >= mapWaitMax) {
        console.log('Failed to load google api');
    }
}

map_load(param1, param2, ...) { // if you need any param

它使用超时等待加载,经过多次尝试后将停止。

1
我认为你的解决方案是最可靠的,但是我会将 else if(mapWaitCount < mapWaitMax) 改为 else if(mapWaitCount <= mapWaitMax),并且将最后一个 else 中的 >= 改为 >,因为如果在开始时增加计数器,它只会尝试 4 次而不是 5 次 :) - Don Diego

1

使用Typescript的方法

现在您可以使用Google Maps JavaScript API Loader库了。

  1. 运行npm i @googlemaps/js-api-loader
  2. 使用加载器
const loader = new Loader({
  apiKey: "",
  version: "weekly"
});

JavaScript方式

  1. 订阅加载器承诺
loader
  .load()
  .then((google) => {
    new google.maps.Map(document.getElementById("map"), mapOptions);
  })
  .catch(e => {
    // do something
  });

库的方式 例如:angular

  1. 订阅加载器承诺
isMapApiLoaded?: boolean

loader
  .load()
  .then((google) => {
     this.isMapApiLoaded = true
  })
  .catch(e => {
    // do something
  });

只有在加载完成后才显示地图。
<google-map *ngIf="isMapApiLoaded"> 
  <!-- ... -->
</google-map>

附加(单例)

  1. 您可以在服务中使用加载器,然后全局导入它
export class MapLoaderService {
  onMapApiDidLoad$: BehaviorSubject<boolean> = new BehaviorSubject(null)
  
  private _initLoader() {
    this.mapLoader
      .load()
      .then((google) => {
        this.onMapApiDidLoad$.next(true)
      })
      .catch((e) => {
        this.onMapApiDidLoad$.next(false)
      })
  }
}

1

更新一个旧问题;在React中,我使用了NPM模块:load-google-maps-api

我开始自己创建这个模块,后来意识到它已经存在,可以节省一些时间。

它将以promise格式加载地图API,因此您可以提供一个回调函数来在加载后执行。

loadGoogleMapsApi().then(function (googleMaps) {
  new googleMaps.Map(document.querySelector('.map'), {
    center: {
      lat: 40.7484405,
      lng: -73.9944191
    },
    zoom: 12
  })
}).catch(function (error) {
  console.error(error)
})

0
这是我制作的通用代码,适用于我的需求。
1)定义在Google地图加载后要执行的函数。
function ToExecuteAfterLoaded()
  {
  // Doing something here ///
  console.log("Executing this function"); // per example //
  }

2) 等待函数

function WhenGoogleLoadedDo(fnt)
   {
   if(typeof google != 'undefined')
      fnt();
   else
      setTimeout(function()
         {(function(fnt)
            {
            WhenGoogleLoadedDo(fnt)
            })(fnt)}, 500); // You can set timer as you wish //
   }

3) 在你的脚本中这样调用 ToExecuteAfterLoaded

WhenGoogleLoadedDo(ToExecuteAfterLoaded);

0

不好。异步操作不能保证在domcontentloaded之前运行,只有延迟操作可以。 - woens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接