Google Maps API 从 ES2015 应用程序失败
Google Maps API fails from ES2015 Application
我正在尝试将我的网站移动到使用 ES2015,包括使用导出和导入来控制对共享资源的访问。这意味着以前使用 HTML 标记显式包含的 javascript 文件现在可以使用 import 语句访问。所以我正在从包含以下内容的页面移动:
<script src="/jscripts/util.js" type="application/javascript">
</script>
<script src="/jscripts/CommonForm.js" type="application/javascript">
</script>
<script src="/jscripts/Cookie.js" type="application/javascript">
</script>
<script src="/FamilyTree/Person.js" type="application/javascript">
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=$GOOGLECC&key=$GOOGLEKEY" type="application/javascript"></script>
到执行以下操作的页面:
<script src="/FamilyTree/Person.js" type="module">
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=$GOOGLECC&key=$GOOGLEKEY" type="application/javascript"></script>
其中 Person.js 开始于:
import HTTP from "../jscripts/js20/http6.js";
import {iframe, actMouseOverHelp, openFrame, openSignon, debug, args,
getOffsetLeft, getOffsetTop, popupAlert, show,
showHelp, hideHelp, helpDiv, helpElt, keyDown,
eltMouseOver, eltMouseOut}
from "../jscripts/util6.js";
import {capitalize} from "../jscripts/CommonForm6.js";
import Cookie from "../jscripts/Cookie6.js";
现在的问题是我的 Google 地图初始化失败,因为它找不到我的回调函数 initializeMaps。那个功能还在。唯一的区别是该文件的更上层包含导入语句。
Uncaught (in promise)
Object { message: "initializeMaps is not a function", name: "InvalidValueError", stack: "ge@https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=CA&key=......:70:72\n_.he@https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=CA&key=....:70:182\nNj@https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=CA&key=.....:146:233\nOj/<@https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=CA&key=.....:146:120\n" }
如何重写我的 Google 地图代码以在 ES2015 中工作?
代码的生产版本示例是 https://www.jamescobban.net/FamilyTree/Person.php?idir=90439&lang=en。将鼠标悬停在任何地名上以利用 Google 地图功能。
不清楚您的 initializeMaps()
函数是在哪个模块中定义的,但是那个特定的 Google API 要求它是一个全局符号,以便 Google 可以找到它当该脚本执行时。而且,它也必须在 Google 脚本执行之前定义。
对于 ES6 模块,脚本中的任何内容都不会自动定义为全局可用。因此,与旧脚本文件不同,脚本中的顶级变量仅具有模块范围,并且在全局范围内不可用。这是 ES6 模块的一个重要变化。您必须 export
一个符号以使其对其他脚本可用,或者您必须通过将其分配给 window
对象(在浏览器中)来显式使其成为全局的,如下所示:
window.initializeMaps = function(...) {...}
也可能 Google 有一个更现代的界面,不需要您像这样定义一个全局符号,这样您就可以使用标准的导入和导出语法。
有关详细信息,您可以在 MDN 上阅读有关 ES6 模块的信息。这是该网页的一组有用的差异。这里最相关的是最后一个要点。
Other differences between modules and standard scripts
You need to pay attention to local testing — if you try to load the HTML file locally (i.e. with a file://
URL), you'll run into CORS
errors due to JavaScript module security requirements. You need to do
your testing through a server.
Also, note that you might get different behavior from sections of script defined inside modules as opposed to in standard scripts. This
is because modules use strict mode automatically.
There is no need to use the defer
attribute (see <script>
attributes) when loading a module script; modules are deferred
automatically.
Modules are only executed once, even if they have been referenced in
multiple <script>
tags.
Last but not least, let's make this clear — module features are imported into the scope of a single script — they aren't available in
the global scope. Therefore, you will only be able to access imported
features in the script they are imported into, and you won't be able
to access them from the JavaScript console, for example. You'll still
get syntax errors shown in the DevTools, but you'll not be able to use
some of the debugging techniques you might have expected to use.
我正在尝试将我的网站移动到使用 ES2015,包括使用导出和导入来控制对共享资源的访问。这意味着以前使用 HTML 标记显式包含的 javascript 文件现在可以使用 import 语句访问。所以我正在从包含以下内容的页面移动:
<script src="/jscripts/util.js" type="application/javascript">
</script>
<script src="/jscripts/CommonForm.js" type="application/javascript">
</script>
<script src="/jscripts/Cookie.js" type="application/javascript">
</script>
<script src="/FamilyTree/Person.js" type="application/javascript">
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=$GOOGLECC&key=$GOOGLEKEY" type="application/javascript"></script>
到执行以下操作的页面:
<script src="/FamilyTree/Person.js" type="module">
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=$GOOGLECC&key=$GOOGLEKEY" type="application/javascript"></script>
其中 Person.js 开始于:
import HTTP from "../jscripts/js20/http6.js";
import {iframe, actMouseOverHelp, openFrame, openSignon, debug, args,
getOffsetLeft, getOffsetTop, popupAlert, show,
showHelp, hideHelp, helpDiv, helpElt, keyDown,
eltMouseOver, eltMouseOut}
from "../jscripts/util6.js";
import {capitalize} from "../jscripts/CommonForm6.js";
import Cookie from "../jscripts/Cookie6.js";
现在的问题是我的 Google 地图初始化失败,因为它找不到我的回调函数 initializeMaps。那个功能还在。唯一的区别是该文件的更上层包含导入语句。
Uncaught (in promise)
Object { message: "initializeMaps is not a function", name: "InvalidValueError", stack: "ge@https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=CA&key=......:70:72\n_.he@https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=CA&key=....:70:182\nNj@https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=CA&key=.....:146:233\nOj/<@https://maps.googleapis.com/maps/api/js?v=3.43&callback=initializeMaps®ion=CA&key=.....:146:120\n" }
如何重写我的 Google 地图代码以在 ES2015 中工作?
代码的生产版本示例是 https://www.jamescobban.net/FamilyTree/Person.php?idir=90439&lang=en。将鼠标悬停在任何地名上以利用 Google 地图功能。
不清楚您的 initializeMaps()
函数是在哪个模块中定义的,但是那个特定的 Google API 要求它是一个全局符号,以便 Google 可以找到它当该脚本执行时。而且,它也必须在 Google 脚本执行之前定义。
对于 ES6 模块,脚本中的任何内容都不会自动定义为全局可用。因此,与旧脚本文件不同,脚本中的顶级变量仅具有模块范围,并且在全局范围内不可用。这是 ES6 模块的一个重要变化。您必须 export
一个符号以使其对其他脚本可用,或者您必须通过将其分配给 window
对象(在浏览器中)来显式使其成为全局的,如下所示:
window.initializeMaps = function(...) {...}
也可能 Google 有一个更现代的界面,不需要您像这样定义一个全局符号,这样您就可以使用标准的导入和导出语法。
有关详细信息,您可以在 MDN 上阅读有关 ES6 模块的信息。这是该网页的一组有用的差异。这里最相关的是最后一个要点。
Other differences between modules and standard scripts
You need to pay attention to local testing — if you try to load the HTML file locally (i.e. with a
file://
URL), you'll run into CORS errors due to JavaScript module security requirements. You need to do your testing through a server.Also, note that you might get different behavior from sections of script defined inside modules as opposed to in standard scripts. This is because modules use strict mode automatically.
There is no need to use the
defer
attribute (see<script>
attributes) when loading a module script; modules are deferred automatically.Modules are only executed once, even if they have been referenced in multiple
<script>
tags.Last but not least, let's make this clear — module features are imported into the scope of a single script — they aren't available in the global scope. Therefore, you will only be able to access imported features in the script they are imported into, and you won't be able to access them from the JavaScript console, for example. You'll still get syntax errors shown in the DevTools, but you'll not be able to use some of the debugging techniques you might have expected to use.