为什么我的 Google Maps API 回调在前面的内联脚本之前执行?
Why is my Google Maps API callback executing before the preceding inline script?
<script src="/js/site.js?v=EtZhOXlkRte5HDRXpfS7rDy3ua0sbCvtNJUaIlNsSXw"></script>
<script>
var init;
$(function () {
var adpSummaryListenerId;
init = _initializeDirections;
initializeAdpSummaryListener();
function _initializeDirections() {
console.log("test"); //we don't get here, sometimes
var origin = {
isGoogle: $("#origin-isgoogle").val(),
coordinate: new google.maps.LatLng(@origin.Latitude, @origin.Longitude),
address: "@origin.StreetAddress",
marker: "@origin.MarkerName"
}, destination = {
isGoogle: $("#destination-isgoogle").val(),
coordinate: new google.maps.LatLng(@destination.Latitude, @destination.Longitude),
address: "@destination.StreetAddress",
marker: "@destination.MarkerName"
}, start = {
value: origin.isGoogle ? origin.address : origin.coordinate,
pos: origin.coordinate,
marker: origin.marker
}, end = {
value: destination.isGoogle ? destination.address : destination.coordinate,
pos: destination.coordinate,
marker: destination.marker
};
console.log("Initializing directions");
initializeDirections(start, end); //in site.js
}
function initializeAdpSummaryListener() {
adpSummaryListenerId = window.setInterval(addNavigateButton, 500);
}
function addNavigateButton() {
console.log("checking for .adp-summary");
if ($(".adp-summary").length) {
$(".adp-summary").append($("#start-navigation").html());
clearInterval(adpSummaryListenerId);
}
}
});
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=@(Model.GoogleMapsApiKey)&callback=init"></script>
我不明白为什么,尽管在 内联脚本 之后引用了地图脚本,Google 地图 API 回调 init
有时在 Google 尝试调用它之前未实例化。
这是我遇到的错误:
Uncaught (in promise)
ld {message: "init is not a function", name: "InvalidValueError", stack: "Error at new ld (https://maps.googleapis.com/.......&callback=init:141:124"}
我之前将回调名称作为 initializeMap
作为在 site.js 中声明的引用(但仍然在内联脚本中初始化),但为了简洁和隔离将其移至此处,希望我能能够弄清楚问题。但同样的问题仍然存在。
我 understand async
指示 api 与解析并行获取并在可用时立即进行评估,但在内联之前不应该可用脚本,对吗?
我也明白defer
表示api在文档解析后才会执行,所以应该还没有。
我确实看到了关于 defer
的内容:
This attribute allows the elimination of parser-blocking JavaScript where the browser would have to load and evaluate scripts before continuing to parse. async has a similar effect in this case.
但是 defer
仍然不应该阻止内联脚本首先执行,因为它只允许 JavaScript 不必被解析器阻塞 如果该属性用于内联 <script>
标记。
所以我很茫然
你上面的内联脚本确实是 运行ning 首先,但是 $(function () {
是一个 jQuery 结构,只有 运行 文档准备好后才会在里面回调.看起来 Google 脚本首先 运行ning。
如果你给 Google 的脚本 defer
属性,它只会 运行 一旦 DOM 完成构建,而 $(function () {
将是不必要的。因此,只需将所有内容移出 $(function () {
,这样 init
将位于顶层,并在 Google 的脚本加载时由 Google 调用:
<script>
function init() {
var origin = {
isGoogle: $("#origin-isgoogle").val(),
coordinate: new google.maps.LatLng(@origin.Latitude, @origin.Longitude),
address: "@origin.StreetAddress",
marker: "@origin.MarkerName"
}, destination =
// etc
请注意,虽然您可以使用 async
或 defer
,但不应同时使用两者。要等到加载 DOM,请使用 defer
而不是 async
。
上面的内联脚本除了分配给变量外还有 一个 事情,即调用 initializeAdpSummaryListener
。如果您需要确保 DOM 在 运行s:
之前加载,您可以将它放在 $(function () {
中
$(initializeAdpSummaryListener);
另一个控制流程可能更容易理解的选项是将 所有内容 放在 Google 加载时调用的命名函数中(考虑到 defer
属性,仅在页面加载后出现)。
<script src="/js/site.js?v=EtZhOXlkRte5HDRXpfS7rDy3ua0sbCvtNJUaIlNsSXw"></script>
<script>
var init;
$(function () {
var adpSummaryListenerId;
init = _initializeDirections;
initializeAdpSummaryListener();
function _initializeDirections() {
console.log("test"); //we don't get here, sometimes
var origin = {
isGoogle: $("#origin-isgoogle").val(),
coordinate: new google.maps.LatLng(@origin.Latitude, @origin.Longitude),
address: "@origin.StreetAddress",
marker: "@origin.MarkerName"
}, destination = {
isGoogle: $("#destination-isgoogle").val(),
coordinate: new google.maps.LatLng(@destination.Latitude, @destination.Longitude),
address: "@destination.StreetAddress",
marker: "@destination.MarkerName"
}, start = {
value: origin.isGoogle ? origin.address : origin.coordinate,
pos: origin.coordinate,
marker: origin.marker
}, end = {
value: destination.isGoogle ? destination.address : destination.coordinate,
pos: destination.coordinate,
marker: destination.marker
};
console.log("Initializing directions");
initializeDirections(start, end); //in site.js
}
function initializeAdpSummaryListener() {
adpSummaryListenerId = window.setInterval(addNavigateButton, 500);
}
function addNavigateButton() {
console.log("checking for .adp-summary");
if ($(".adp-summary").length) {
$(".adp-summary").append($("#start-navigation").html());
clearInterval(adpSummaryListenerId);
}
}
});
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=@(Model.GoogleMapsApiKey)&callback=init"></script>
我不明白为什么,尽管在 内联脚本 之后引用了地图脚本,Google 地图 API 回调 init
有时在 Google 尝试调用它之前未实例化。
这是我遇到的错误:
Uncaught (in promise)
ld {message: "init is not a function", name: "InvalidValueError", stack: "Error at new ld (https://maps.googleapis.com/.......&callback=init:141:124"}
我之前将回调名称作为 initializeMap
作为在 site.js 中声明的引用(但仍然在内联脚本中初始化),但为了简洁和隔离将其移至此处,希望我能能够弄清楚问题。但同样的问题仍然存在。
我 understand async
指示 api 与解析并行获取并在可用时立即进行评估,但在内联之前不应该可用脚本,对吗?
我也明白defer
表示api在文档解析后才会执行,所以应该还没有。
我确实看到了关于 defer
的内容:
This attribute allows the elimination of parser-blocking JavaScript where the browser would have to load and evaluate scripts before continuing to parse. async has a similar effect in this case.
但是 defer
仍然不应该阻止内联脚本首先执行,因为它只允许 JavaScript 不必被解析器阻塞 如果该属性用于内联 <script>
标记。
所以我很茫然
你上面的内联脚本确实是 运行ning 首先,但是 $(function () {
是一个 jQuery 结构,只有 运行 文档准备好后才会在里面回调.看起来 Google 脚本首先 运行ning。
如果你给 Google 的脚本 defer
属性,它只会 运行 一旦 DOM 完成构建,而 $(function () {
将是不必要的。因此,只需将所有内容移出 $(function () {
,这样 init
将位于顶层,并在 Google 的脚本加载时由 Google 调用:
<script>
function init() {
var origin = {
isGoogle: $("#origin-isgoogle").val(),
coordinate: new google.maps.LatLng(@origin.Latitude, @origin.Longitude),
address: "@origin.StreetAddress",
marker: "@origin.MarkerName"
}, destination =
// etc
请注意,虽然您可以使用 async
或 defer
,但不应同时使用两者。要等到加载 DOM,请使用 defer
而不是 async
。
上面的内联脚本除了分配给变量外还有 一个 事情,即调用 initializeAdpSummaryListener
。如果您需要确保 DOM 在 运行s:
$(function () {
中
$(initializeAdpSummaryListener);
另一个控制流程可能更容易理解的选项是将 所有内容 放在 Google 加载时调用的命名函数中(考虑到 defer
属性,仅在页面加载后出现)。