如何异步加载具有document.write

时间:2015-08-28 00:33:45

标签: javascript document.write external-script

我们提供了一些javascript标记,例如<script src="http://ours.com/some.js"></script>网站所有者在其网站上放置http://example.com,并且在此javascript标记中我们希望动态包含第三方js,例如哪个可以其中有document.write,但当然如果我们尝试用传统方法包含它,

var script_tag = document.createElement('script');
script_tag.type = 'text/javascript';
script_tag.src="http://third-party.com/some.js";
document.getElementById('target').appendChild(script_tag);

我们从浏览器收到警告

  

警告:从异步加载的对document.write()的调用   外部脚本被忽略了。

我们如何解决这个问题?请记住,我们并不真正控制第三方脚本,因此我们无法更改其中的逻辑。我们正在寻找一种适用于所有浏览器的解决方案。

7 个答案:

答案 0 :(得分:3)

在已加载的文档上加载脚本(而不是让浏览器忽略document.write())的问题是您将删除所有现有的HTML。请参阅this example,以便您可以准确了解正在发生的事情,或者有关详细信息,请查看document {.write()方法的documentation page

虽然我知道这可能不是您期望得到的答案,但我相信您运气不好,因为重写脚本不是一种选择。

This似乎是一个类似的问题,也有类似的回复。

答案 1 :(得分:1)

通过以这种方式拦截对document.write的调用,您可以以正确的方式支持脚本注入:

document.writeText = document.write;

document.write = function(parameter) {
    if (!parameter) return; 
    var scriptPattern = /<script.*?src=['|"](.*?)['|"]/;
    if (scriptPattern.test(parameter)) {
        var srcAttribute = scriptPattern.exec(parameter)[1];
        var script = document.createElement('script');
        script.src = srcAttribute;
        document.head.appendChild(script); 
    }
    else {
        document.writeText(parameter);
    }   
};

显然,这可以进一步缩小,但为了清楚起见,包含了变量名称。

Source

答案 2 :(得分:0)

如何通过附加脚本元素来加载脚本,而不是通过AJAX调用加载脚本URL的内容,然后使用eval()在全局范围内运行它?这是一个例子,我测试了它以验证它是否有效:

public void MySlider_ManipulationDelta(object sender, 
  ManipulationDeltaRoutedEventArgs e)
{
    var velocities = e.Velocities
    var slider = sender as Slider;
    if(slider != null)
    {
        //Create a fomula based on the velocities to fit your needs.
    }

}

以下是我在test.js文件中的内容:

<!DOCTYPE html>
<html>
<head>
<script>

var xmlhttp;

if (window.XMLHttpRequest) {
  xmlhttp = new XMLHttpRequest();
}else{
  xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}

xmlhttp.onreadystatechange = function() {
  if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
    window.eval(xmlhttp.responseText); //Indirect call to eval to execute in global scope (http://perfectionkills.com/global-eval-what-are-the-options/)
  }
}

xmlhttp.open("GET", "https://third-party.com/test.js", false); //This is synchronous so that any document.write calls don't overwrite the entire page when they get called after the document is finished rendering. For all intents and purposes, this just loads the script like any other script, synchronously.

xmlhttp.send();

</script>
</head>
<body>

<div><h2>Hello World</h2></div>

</body>
</html>

我对脚本的AJAX请求是同步的,因此它的加载方式就像是常规的嵌入式脚本标记一样。如果你异步运行它,并且脚本在页面完全呈现后使用document.write,它会清除DOM然后写入它...实际上有点烦人。 Lemme知道这是否适合你。 :)

答案 3 :(得分:0)

Document.write将无法在异步脚本中运行,因为脚本开始工作时已经加载了文档。

但你可以这样做:

document.body.innerHTML = document.body.innerHTML + '<h1>Some HTML</h1>';

答案 4 :(得分:0)

另一个程序是改变document.write()功能的行为 假设您有主index.php文件:

<html>
<head>
<meta charset="utf-8" />
</head>
<body>
Hello<br>
<div id="target"></div>
<script>
document.write = function(input) {
    document.body.innerHTML += input;
}
var doit = function() {
    var script_tag = document.createElement('script');
    script_tag.type = 'text/javascript';
    script_tag.src="http://127.0.0.1:8080/testPlace/jsfile.js";
    document.getElementById('target').appendChild(script_tag);
}
</script>
</body>
</html>

并且jsfile.js是这样的:

document.write("OK MAN!");

现在,如果您在js浏览器控制台中键入doit()来执行该功能(并且脚本执行您所写的操作),那么结果将是:

Hello
OK MAN!

其中html是这样的:

<html><head>
<meta charset="utf-8">
</head>
<body>
Hello<br>
<div id="target"><script src="http://127.0.0.1:8080/testPlace/jsfile.js" type="text/javascript"></script></div>
<script>
    //That Script which here I removed it to take less space in answer
</script>

OK MAN!</body>
</html>

答案 5 :(得分:-1)

什么是第三方javascript文件?

如果是Google Maps JavaScript API v3,请确保在脚本网址中包含“&amp; callback = your_init_funct”。然后,一旦加载了地图库,它就会调用'your_init_funct',以便您可以开始显示地图。

另一个解决方案是bezen.domwrite.js,可在此处找到:http://bezen.org/javascript/index.html

演示:http://bezen.org/javascript/test/test-domwrite.html

答案 6 :(得分:-1)

是的,无法从异步加载的脚本中调用document.write,因为它与文档分离,因此无法写入文档。

你可以看到这里用于google maps api的方法来解决这个问题。因此,有些您未命名的第三方脚本可能会实现类似的回调模式。

https://developers.google.com/maps/documentation/javascript/examples/map-simple?hl=EN

<!DOCTYPE html>
<html>
  <head>
    <title>Simple Map</title>
    <meta name="viewport" content="initial-scale=1.0">
    <meta charset="utf-8">
    <style>
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
      #map {
        height: 100%;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>
    <script>

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: -34.397, lng: 150.644},
    zoom: 8
  });
}

    </script>
    <script src="https://maps.googleapis.com/maps/api/js?callback=initMap"
        async defer></script>
  </body>
</html>