gaoluyang
2026-06-24 c0cb161bb52ce0fbdce5c66ec391d107c75e2452
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/* eslint-disable @typescript-eslint/no-dynamic-delete */
/**
 * 百度地图 SDK 加载工具
 */
 
// 扩展 Window 接口以包含百度地图 GL API
declare global {
  interface Window {
    BMapGL: any;
  }
}
 
// 全局回调名称
const CALLBACK_NAME = '__BAIDU_MAP_LOAD_CALLBACK__';
 
// SDK 加载状态
let loadPromise: null | Promise<void> = null;
 
/**
 * 加载百度地图 GL SDK
 * @param timeout 超时时间(毫秒),默认 10000
 * @returns Promise<void>
 */
export const loadBaiduMapSdk = (timeout = 10_000): Promise<void> => {
  // 已加载完成
  if (window.BMapGL) {
    return Promise.resolve();
  }
 
  // 正在加载中,返回同一个 Promise
  if (loadPromise) {
    return loadPromise;
  }
 
  loadPromise = new Promise((resolve, reject) => {
    const timeoutId = setTimeout(() => {
      loadPromise = null;
      reject(new Error('百度地图 SDK 加载超时'));
    }, timeout);
 
    // 全局回调
    (window as any)[CALLBACK_NAME] = () => {
      clearTimeout(timeoutId);
      delete (window as any)[CALLBACK_NAME];
      resolve();
    };
 
    // 创建 script 标签
    const script = document.createElement('script');
    script.src = `https://api.map.baidu.com/api?v=1.0&type=webgl&ak=${
      import.meta.env.VITE_BAIDU_MAP_KEY
    }&callback=${CALLBACK_NAME}`;
    script.addEventListener('onerror', () => {
      clearTimeout(timeoutId);
      loadPromise = null;
      delete (window as any)[CALLBACK_NAME];
      reject(new Error('百度地图 SDK 加载失败'));
    });
    document.body.append(script);
  });
 
  return loadPromise;
};