繁体   English   中英

为什么我的 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 尝试调用它之前不会实例化 Google Maps API 回调init

这是我得到的错误:

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 中声明的引用(但仍然在内联脚本中在这里初始化),但为了简洁和隔离,将它移到这里,希望我能够找出问题所在。 但同样的问题仍然存在。

知道async指示 api 在解析和评估可用时并行获取,但它不应该在内联脚本之前可用,对吗?

我也明白defer表示在解析文档之后才会执行 api,所以它仍然不应该可用。

我确实看到了这个关于defer

此属性允许消除阻止解析器的 JavaScript,浏览器在继续解析之前必须加载和评估脚本。 在这种情况下,异步具有类似的效果。

但是defer仍然不应该阻止内联脚本首先执行,因为如果在内联<script>标签上使用该属性,它只会使 JavaScript不必被解析器阻塞

所以我不知所措。

您上面的内联脚本确实首先运行,但是$(function () {是一个 jQuery 构造,它只在文档准备好后才在内部运行回调。看起来 Google 脚本首先运行。

如果您为 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

请注意,虽然您可以使用asyncdefer ,但您不应同时使用两者。 要等到 DOM 加载完毕,请使用defer而不是async

除了分配给变量之外,您上面的内联脚本还有件事是调用initializeAdpSummaryListener 你可以把它放在$(function () {如果你需要确保在运行之前加载 DOM:

$(initializeAdpSummaryListener);

另一个控制流程可能更容易理解的选项是将所有内容放在 Google 在加载时调用的命名函数中(给定defer属性,该函数仅在页面加载时发生)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM