起因
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=您的密钥')
// 加载失败
发现控制台有个警告
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
})
}