问题 async使用document.write加载javascript


我试图异步谷歌地图api javascript。

因此,正常的脚本标记有效 <script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>

但是,以下异步版本没有。

(function () {
    var gmap = document.createElement('script'); gmap.type = 'text/javascript'; gmap.async = true;
    gmap.src = 'https://maps.googleapis.com/maps/api/js?sensor=false';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(gmap, s);
})();

经过一些断点+检查操作后,我发现该行在异步模式下无法正常运行。

document.write('<' + 'script src="' + src + '"' + 
' type="text/javascript"><' + '/script>');

同步模式下的文档对象是“HTMLDocument”,但在异步模式下则是“#document”。加载页面后,文档对象发生了某些变化。思考?

干杯。

更新: 这个问题更多的是为什么不会触发document.write而不是异步加载google map api。如果在此行上设置断点,则可以看到document.write函数存在。这与document.write是本机的事实有什么关系吗?


6970
2017-10-22 00:35


起源



答案:


document.write 无法从异步脚本调用,因为它与文档分离,因此您的JS解析器不知道将它放在何处。充其量,浏览器会忽略它。在最坏的情况下,它可以写在当前文档的顶部(如在文档加载完成后调用document.write的情况)。

不幸的是,唯一的答案是重写脚本,在google api的情况下可能不是一个可行的选择。


7
2017-10-22 00:47



谢谢。我在这一行上做了断点并尝试自己记录。写。它确实找到了write()函数,这就是为什么它很奇怪。如果分离了写函数,那为什么它不是未定义的? - user1736525
是的谷歌是一个笑话 - neaumusic


答案:


document.write 无法从异步脚本调用,因为它与文档分离,因此您的JS解析器不知道将它放在何处。充其量,浏览器会忽略它。在最坏的情况下,它可以写在当前文档的顶部(如在文档加载完成后调用document.write的情况)。

不幸的是,唯一的答案是重写脚本,在google api的情况下可能不是一个可行的选择。


7
2017-10-22 00:47



谢谢。我在这一行上做了断点并尝试自己记录。写。它确实找到了write()函数,这就是为什么它很奇怪。如果分离了写函数,那为什么它不是未定义的? - user1736525
是的谷歌是一个笑话 - neaumusic


在异步加载亚马逊广告时,我遇到了一个非常类似的问题。我能够得到 document.write 通过改变其行为在我的应用程序中近似这些情况($ 在这种情况下指的是jQuery):

document.write = function(content) {
  if (document.currentScript) {
    var src = document.currentScript.src
        .replace(/\#.*$/, '')
        .replace(/\?.*$/, '')
        .replace(/^.*\/\//, '');
    setTimeout(function() {
      var script = $('script').filter(function() {
        var scriptSrc = $(this).attr('src');
        return scriptSrc && scriptSrc.indexOf(src) !== -1;
      });
      $('<div></div>')
          .addClass('doc-write')
          .html(content)
          .insertAfter(script);
    }, 0);
  } else {
    HTMLDocument.prototype.write.apply(document, arguments);
  }
};

这种方法可以改进,但它足以满足我的需求。希望你会发现它很有用。


5
2018-03-24 16:03



刚刚投了这个,但现在意识到这不是IE 11的支持。有什么建议吗? - downatone
使用 callback=somefunction 具有初始api负载的param - neaumusic


使用参数时 callback 在脚本URL内,脚本不使用 write() 并且您将能够异步加载API。

看到: https://developers.google.com/maps/documentation/javascript/tutorial?hl=en#asynch


2
2017-10-22 02:16



是的,我有回调但我在jquery mobile中遇到了另一个问题,它多次加载google map api。我不喜欢警告信息。 - user1736525
如果您不喜欢警告,请不要多次加载API。 - Dr.Molle
它是使用jqm ajax模式的asp mvc中的jquery mobile。因此,加载API一次而不是使用jqm事件似乎更简洁。 - user1736525


不使用 document.write(),由于市场和Molle博士解释的原因。使用 appendChild() 相反,就像在 Google的异步加载示例


1
2017-10-22 07:16



不再是“map-simple-async”。只有“地图简单”。所以这个答案不再有用了:( - Anton Kolenkov


在这里添加评论,因为我在这个问题上挣扎了很多。异步加载脚本时(例如通过按钮单击),请确保按照说明进行操作 究竟 就像在 现场

我第一次得到了 document.write 我没有给出回调值时出错。在给出回调之后,我得到了回复 window.initialize 错误,因为... duh ...我的代码中没有初始化函数。我将其更改为我的函数名称(类似于loadMap),它开始工作。

说实话,只需从网站上复制代码即可。更换 window.onload 无论你需要什么来触发所述功能。


0
2017-07-14 11:07