通过外部 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