You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 4中如何延迟声明google直至异步延迟JS加载完成?

这个问题我太熟了!给Google API脚本加async defer确实能优化页面加载性能,但也会踩时序冲突的坑——Angular组件先初始化完成,可Google Maps的JS还没加载好,自然就抛出ReferenceError: google is not defined了。下面给你几个实用的解决方案,按需挑选就行:

方法1:利用Google API的回调参数(最简单直接)

Google Maps API原生支持指定回调函数,脚本加载完成后会自动执行它。我们可以通过这个回调标记Google服务就绪,再让组件等待这个标记后初始化地图。

步骤如下:

  1. 修改index.html里的脚本标签,添加callback参数:
<script async defer src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&callback=initGoogleMaps"></script>
  1. 在全局作用域定义回调函数(可以放在index.html的<script>标签里,或者main.ts中挂载到window):
// 标记Google Maps已加载完成
window.initGoogleMaps = () => {
  window['googleLoaded'] = true;
};
  1. 在app.component.ts中等待标记生效后再初始化地图:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  ngOnInit(): void {
    this.waitForGoogleMaps().then(() => {
      // 这里可以安全使用google对象了
      const map = new google.maps.Map(document.getElementById('map'), {
        center: { lat: -34.397, lng: 150.644 },
        zoom: 8
      });
    });
  }

  private waitForGoogleMaps(): Promise<void> {
    return new Promise(resolve => {
      // 如果已经加载完成直接返回
      if (window['googleLoaded']) {
        return resolve();
      }
      // 轮询检查加载状态
      const interval = setInterval(() => {
        if (window['googleLoaded']) {
          clearInterval(interval);
          resolve();
        }
      }, 100);
    });
  }
}
方法2:用RxJS监听脚本加载事件(更贴合Angular风格)

不想用全局回调的话,可以直接监听脚本的load事件,用RxJS处理异步流:

  1. 给index.html里的脚本加个id,方便获取元素:
<script async defer id="google-maps-script" src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY"></script>
  1. 在app.component.ts中监听脚本加载完成事件:
import { Component, OnInit } from '@angular/core';
import { fromEvent } from 'rxjs';
import { take } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  ngOnInit(): void {
    const scriptElement = document.getElementById('google-maps-script');
    if (!scriptElement) return;

    // 如果脚本已经加载完成,直接初始化
    if (scriptElement['readyState'] === 'complete' || scriptElement['readyState'] === 'loaded') {
      this.initMap();
    } else {
      // 监听脚本加载完成的事件
      fromEvent(scriptElement, 'load').pipe(take(1)).subscribe(() => {
        this.initMap();
      });
    }
  }

  private initMap(): void {
    const map = new google.maps.Map(document.getElementById('map'), {
      center: { lat: -34.397, lng: 150.644 },
      zoom: 8
    });
  }
}
方法3:用APP_INITIALIZER全局预加载(适合全应用依赖Maps的场景)

如果你的整个Angular应用都依赖Google Maps,可以用APP_INITIALIZER在应用启动前就加载好Maps服务,这样所有组件都能直接使用google对象:

  1. 在app.module.ts中配置APP_INITIALIZER:
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';

// 加载Google Maps的工厂函数
export function loadGoogleMaps(): Promise<void> {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = 'https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY';
    script.async = true;
    script.defer = true;
    script.onload = () => resolve();
    script.onerror = () => reject(new Error('加载Google Maps API失败'));
    document.body.appendChild(script);
  });
}

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: loadGoogleMaps,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
  1. 之后在app.component.ts里就能直接初始化地图,不用再等待:
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  ngOnInit(): void {
    this.initMap();
  }

  private initMap(): void {
    const map = new google.maps.Map(document.getElementById('map'), {
      center: { lat: -34.397, lng: 150.644 },
      zoom: 8
    });
  }
}
额外小贴士:解决TypeScript报错

为了让TypeScript不报错(它默认不知道全局的google对象),你可以:

  • 安装官方类型声明:npm install @types/googlemaps --save-dev
  • 或者在项目根目录创建typings.d.ts文件,手动添加声明:
declare var google: any;

内容的提问来源于stack exchange,提问作者j4rey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:52:59