[Vue 项目技巧] 异步加载百度地图 jssdk

1,442 阅读1分钟

起因

Vue 项目中要引入百度地图 jssdk https://api.map.baidu.com/api?v=3.0&ak=您的密钥,项目中的其他 jssdk 都是用如下方法异步加载的,但引入百度地图 jssdk 失败了。

function loadJavascript(url) {
  return new Promise((resolve, reject) => {
    const scriptEl = document.createElement('script')
    scriptEl.type = 'text/javascript'
    scriptEl.src = url
    document.body.appendChild(scriptEl)
    scriptEl.onload = resolve
    scriptEl.onerror = reject
  })
}
await loadJavascript('https://api.map.baidu.com/api?v=3.0&ak=您的密钥')
// 加载失败

发现控制台有个警告

image.png

Failed to execute 'write' on 'Document': It isn't possible to write into a document from an asynchronously-loaded external script unless it is explicitly opened.

打开这个 sdk 内容如下:

(function(){window.BMAP_PROTOCOL = "https"; window.BMap_loadScriptTime = (new Date).getTime(); document.write('<script type="text/javascript" src="https://api.map.baidu.com/getscript?v=3.0&ak=您的密钥&services=&t=20211206192911"></script>');})();

查到的资料是说,加载失败的原因是 DOM 已经加载完毕,关闭了加载通道,document.write 不能异步了,所以加载不了

index.html 中直接引入是没问题的,但项目中只有少数场景用到,没必要一开始就引入。

<script type="text/javascript" src="https://api.map.baidu.com/api?v=3.0&ak=您的密钥">

解决方法

百度地图 jssdk 是支持 JSONP 实现异步加载的。

export function LoadBMapScript() {
  return new Promise((resolve, reject) => {
    window.onBMapInitialize = resolve
    const scriptEl = document.createElement('script')
    scriptEl.type = 'text/javascript'
    scriptEl.src =
      'https://api.map.baidu.com/api?v=3.0&ak=您的密钥&callback=onBMapInitialize'
    document.body.appendChild(scriptEl)
    scriptEl.onerror = reject
  })
}