通过外部 CDN 加载的全局对象在运行时不可用的回调中使用
Global object loaded through external CDN used in callback not available at runtime
我正在使用 BingMaps Api。我使用 JavaScript 将脚本标记附加到加载 CDN 的 DOM 中。然后我声明一个全局函数,当 CDN 加载时用作回调,如文档所述。
然而,当回调为 运行 时,我不断收到 "TypeError: Microsoft.Map is not a constructor"。
当我在控制台中输入 "Microsoft" 时,我看到它就在那里。当我将脚本直接放入 HTML 时,不会发生此问题。这是为什么?
可以在此沙箱中查看和执行代码:https://codesandbox.io/s/1z4o7km3ml
// insert script tag into DOM
const bingScript = document.createElement("script");
bingScript.type = "text/javascript";
bingScript.src =
"https://www.bing.com/api/maps/mapcontrol?callback=onLoadApi";
document.head.appendChild(bingScript);
//insert div element into DOM
const mapDiv = document.createElement("div");
mapDiv.id = "bingMap";
mapDiv.setAttribute("style",
"position:relative;width:600px;height:400px;");
document.body.appendChild(mapDiv);
window.onLoadApi = () => {
try {
const map = new
window.Microsoft.Map(document.getElementById("bingMap"), {
credentials:
<API KEY>
});
} catch (e) {
console.error(e);
}
};
我不知道为什么以前的代码不起作用。即使在 运行 createMap() 函数之前设置了五秒的超时,Microsoft 对象仍然不可用。如果有人能提供洞察力,我们将不胜感激。但解决方案是将回调包装在一个承诺中。
import "./styles.css";
let initializedPromise = null
//insert div element into DOM
const mapDiv = document.createElement("div");
mapDiv.id = "bingMap";
mapDiv.setAttribute("style", "position:relative;width:600px;height:400px;");
document.body.appendChild(mapDiv);
const insertBingScriptIntoDom = () => {
const bingScript = document.createElement("script");
bingScript.type = "text/javascript";
bingScript.src =
"https://www.bing.com/api/maps/mapcontrol?callback=onLoadApi;
document.body.appendChild(bingScript);
};
const initApi = () => {
if (!initializedPromise) {
initializedPromise = new Promise((resolve, reject) => {
window.onLoadApi = () => {
resolve()
}
})
insertBingScriptIntoDom()
}
return initializedPromise
}
const createMap = async () => {
await initApi()
new window.Microsoft.Maps.Map(mapDiv, {
credentials: <API KEY>,
center: window.Microsoft.Maps.Location(41.6, 2.9)
})
}
createMap()
事实上,除了实例化地图对象的那一行之外,您的示例一切正常:
const map = new window.Microsoft.Map(document.getElementById("bingMap"), {
^^^^^^^^^^^^^^^^^^^^
credentials: API_KEY
});
这里有一个错字,Map
class is declared under Microsoft.Maps
namespace,但是 不是 Microsoft
命名空间下的 ,如您的示例,这就是发生指定错误的原因:
TypeError: window.Microsoft.Map is not a constructor
我正在使用 BingMaps Api。我使用 JavaScript 将脚本标记附加到加载 CDN 的 DOM 中。然后我声明一个全局函数,当 CDN 加载时用作回调,如文档所述。
然而,当回调为 运行 时,我不断收到 "TypeError: Microsoft.Map is not a constructor"。
当我在控制台中输入 "Microsoft" 时,我看到它就在那里。当我将脚本直接放入 HTML 时,不会发生此问题。这是为什么?
可以在此沙箱中查看和执行代码:https://codesandbox.io/s/1z4o7km3ml
// insert script tag into DOM
const bingScript = document.createElement("script");
bingScript.type = "text/javascript";
bingScript.src =
"https://www.bing.com/api/maps/mapcontrol?callback=onLoadApi";
document.head.appendChild(bingScript);
//insert div element into DOM
const mapDiv = document.createElement("div");
mapDiv.id = "bingMap";
mapDiv.setAttribute("style",
"position:relative;width:600px;height:400px;");
document.body.appendChild(mapDiv);
window.onLoadApi = () => {
try {
const map = new
window.Microsoft.Map(document.getElementById("bingMap"), {
credentials:
<API KEY>
});
} catch (e) {
console.error(e);
}
};
我不知道为什么以前的代码不起作用。即使在 运行 createMap() 函数之前设置了五秒的超时,Microsoft 对象仍然不可用。如果有人能提供洞察力,我们将不胜感激。但解决方案是将回调包装在一个承诺中。
import "./styles.css";
let initializedPromise = null
//insert div element into DOM
const mapDiv = document.createElement("div");
mapDiv.id = "bingMap";
mapDiv.setAttribute("style", "position:relative;width:600px;height:400px;");
document.body.appendChild(mapDiv);
const insertBingScriptIntoDom = () => {
const bingScript = document.createElement("script");
bingScript.type = "text/javascript";
bingScript.src =
"https://www.bing.com/api/maps/mapcontrol?callback=onLoadApi;
document.body.appendChild(bingScript);
};
const initApi = () => {
if (!initializedPromise) {
initializedPromise = new Promise((resolve, reject) => {
window.onLoadApi = () => {
resolve()
}
})
insertBingScriptIntoDom()
}
return initializedPromise
}
const createMap = async () => {
await initApi()
new window.Microsoft.Maps.Map(mapDiv, {
credentials: <API KEY>,
center: window.Microsoft.Maps.Location(41.6, 2.9)
})
}
createMap()
事实上,除了实例化地图对象的那一行之外,您的示例一切正常:
const map = new window.Microsoft.Map(document.getElementById("bingMap"), {
^^^^^^^^^^^^^^^^^^^^
credentials: API_KEY
});
这里有一个错字,Map
class is declared under Microsoft.Maps
namespace,但是 不是 Microsoft
命名空间下的 ,如您的示例,这就是发生指定错误的原因:
TypeError: window.Microsoft.Map is not a constructor