我的心<;脚本>;在目标页面';s javascript,尽管在:document\u start使用run\u?

我的心<;脚本>;在目标页面';s javascript,尽管在:document\u start使用run\u?,javascript,google-chrome-extension,content-script,Javascript,Google Chrome Extension,Content Script,当我使用内容脚本将一些javascript注入HTML页面时,javascript的执行顺序出现了一些问题: 这是我用来测试的HTML页面,test.HTML: <html><head> <title>Test Page</title></head> <body> <script> console.log("In page"); </script> <

当我使用内容脚本将一些javascript注入HTML页面时,javascript的执行顺序出现了一些问题:

这是我用来测试的HTML页面,test.HTML

<html><head>    
<title>Test Page</title></head>
  <body>
    <script>
      console.log("In page");
    </script>
  </body>
</html>
var s = document.createElement("script");
s.src = chrome.extension.getURL("inject.js");
document.documentElement.appendChild(s);
console.log("Inject finished");
console.log("Inside inject.js");
  "web_accessible_resources": [
    "inject.js"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["/injector.js"],
      "run_at": "document_start"
    }
  ]

这是注入脚本的内容,inject.js

<html><head>    
<title>Test Page</title></head>
  <body>
    <script>
      console.log("In page");
    </script>
  </body>
</html>
var s = document.createElement("script");
s.src = chrome.extension.getURL("inject.js");
document.documentElement.appendChild(s);
console.log("Inject finished");
console.log("Inside inject.js");
  "web_accessible_resources": [
    "inject.js"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["/injector.js"],
      "run_at": "document_start"
    }
  ]

最后,这是我的manifest.json

<html><head>    
<title>Test Page</title></head>
  <body>
    <script>
      console.log("In page");
    </script>
  </body>
</html>
var s = document.createElement("script");
s.src = chrome.extension.getURL("inject.js");
document.documentElement.appendChild(s);
console.log("Inject finished");
console.log("Inside inject.js");
  "web_accessible_resources": [
    "inject.js"
  ],
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["/injector.js"],
      "run_at": "document_start"
    }
  ]

我的问题是,为什么页面中的
要在
inject.js
之前打印出来?既然我将
run\u设置为
document\u start
,那么
inject.js不应该首先运行吗

如果这是出于设计,是否有任何方法可以确保inject.js中的内容在HTML页面中的脚本执行之前执行,而不更改HTML页面中的任何内容

appendChild
之前将
async
属性设置为
false
似乎不起作用,因为它用于外部脚本之间的排序,而不是外部脚本和页面内脚本之间的排序


顺便说一句,我正在Chrome 27.0.1453.9上测试这一点,当你像那样将javascript注入页面时,它是异步的。当您从一开始就将
标记放在那里时,它将是同步的,并以正确的顺序运行

有点麻烦,但由于它是异步的,所以在加载另一个脚本文件时,代码将继续执行


为了知道脚本何时完成,您必须处理脚本的事件-最简单的方法是使用jQuery的
getScript
函数,它为您提供了一个回调参数。

script
标记没有阻止执行(谢天谢地!)。如果希望获得所需的功能(延迟加载),则需要执行以下操作:

function loadScript(scriptName, callback) {
   var sTag = document.createElement("script");
   sTag.src = scriptName;
   sTag.onreadystatechange = sTag.onload = function() {
    var state = s.readyState;

    if (!state || /loaded|complete/.test(state)) {
        callback();
    }
  };
 }

这将在加载脚本标记时触发回调函数。从那里,加载所有内容并确保每个回调都已处理,然后在您拥有所需的每个库的情况下启动页面加载事件。

注入脚本,带有
src
属性,在Chrome中异步执行。
考虑这个HTML文件:


Chrome早期脚本注入,测试页面
var s=document.createElement(“脚本”);
s、 src=“localInject1.js”;
document.documentElement.appendChild;
请参阅控制台

log(“在页面:,new Date().getTime());
其中,localInject1.js只是:

console.log("In page's script 1: ", new Date().getTime());
localInject2.js是:

console.log("In page's script 2: ", new Date().getTime());

名义上,控制台应显示:

在页面的脚本1中:。。。
在页面的脚本2中:。。。
在第页:。。。

但通常,尤其是在无缓存重新加载时,您会看到:

在页面的脚本2中:。。。
在第页:。。。
在页面的脚本1中:。。。

设置
s.async=false没有区别


我不确定这是否是一个错误。Firefox也会使脚本混乱,但似乎更为一致。似乎没有,规格对我来说也不清楚


解决办法: 由
textContent
设置代码的脚本,而不是由
src
链接的文件,会像您所期望的那样立即执行。
例如,如果将injector.js更改为:

var s = document.createElement ("script");
s.src = chrome.extension.getURL ("inject.js");
document.documentElement.appendChild (s);

var s = document.createElement ('script');
s.textContent = 'console.log ("Text runs correctly!", new Date().getTime() );';
document.documentElement.appendChild (s);

console.log("Inject finished", new Date().getTime() );
你会看到:

文本运行正常。。。
注射完成。。。
第页
inspect.js内部


诚然,这可能是内容脚本中的一个难题,但在W3C和浏览器供应商解决此问题之前,这可能是(在Chrome中)您所能做的一切。

有整个库专门用于实现您正在尝试的功能,因为每个浏览器似乎都添加了自己的bug。看看HeadJS之类的东西,或者如果已经在使用jQuery joe说的话。

Hi,我相信你是想在html页面中使用getScript,对吗?我的问题又添了一个麻烦:“……但在html页面内什么都没有改变?”。有什么想法吗?如果不更改HTML,我不知道如何-为了让脚本在脚本之前运行,您必须在页面上的脚本标记之前添加一个脚本标记。但是你可以用这些扩展做很多有趣的事情,所以也许有一些事情我没听说过。Joe的答案和HeadJS都不适用于这个Chrome扩展问题。OP无法控制目标页面的源代码(他的SSCCE,示例HTML只是为了以简洁的方式说明问题的本质)。我认为变通解决方案的唯一问题是难以用字符串编写代码。使用脚本生成它可能会有所帮助。我在这里写了一篇。实际上,@Hui.Li,用javascript将代码转换成字符串相当容易。只需将其包装在函数中,例如:
function foo(){/*您的代码放在这里*/}
,然后在函数上使用
.toString()
。例如:
s.textContent='('+foo.toString()+')();'
@BrockAdams在文档开始执行此脚本之前,有没有一种方法可以传递一些非常基本的消息?@SrikanthRayabhagi,您需要提出一个新问题,详细说明您正在尝试做什么。