我的心<;脚本>;在目标页面';s javascript,尽管在:document\u start使用run\u?
当我使用内容脚本将一些javascript注入HTML页面时,javascript的执行顺序出现了一些问题: 这是我用来测试的HTML页面,test.HTML:我的心<;脚本>;在目标页面';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> <
<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,您需要提出一个新问题,详细说明您正在尝试做什么。