javascript - Chrome 扩展设置为 `run_at` `document_start` 运行速度太快?

标签 javascript google-chrome google-chrome-extension userscripts content-script

编辑:我的 Chrome 浏览器出现问题并与我的脚本发生冲突,完全重新安装消除了问题源。如果我碰巧发现是什么原因造成的,我会把它包括在这里。

EDIT2:只是为了让在 2017 年阅读本文的任何人都知道我没有忘记这一点,而且自从我上次编辑以来我从未遇到过这个问题。

EDIT3:现在是 2019 年,到目前为止我再也没有遇到过这个问题。


我一直在学习如何创建一个简单的 Chrome 扩展,它是一个用户脚本端口。该脚本与 Tampermonkey 完美配合,将 run at 设置为 document-start,所有需要从头开始捕获的必要事件都被捕获。

但是,当我在 Chrome 扩展程序中设置相同的设置时,我发现相同的运行设置比 Tampermonkey 的设置更快,这导致第一个函数失败:(Uncaught TypeError: Cannot call method 'appendChild' of null. ) 因为它试图将脚本元素附加到 head 部分,该部分直到 0.010 秒后才存在。

到目前为止,我的肮脏解决方案一直是使用 setInterval 函数并将计时器设置为 10 来检查 document.head 是否存在,然后继续执行代码如果条件为真。

有什么方法可以让我正确地工作而不必求助于 setInterval 或复制 Tampermonkey 的 grant none 选项,该选项似乎在网页上运行用户脚本上下文?

以下是我的 manifest.json 文件:

{
    "manifest_version": 2,
    "content_scripts": [ {
        "js":        [ "simpleuserscript.user.js" ],
        "matches":   [ "https://www.google.com/*"],
        "run_at":    "document_start"
    } ],
    "converted_from_user_script": true,
    "description":  "Chrome extension",
    "name":         "Testing",
    "version":      "1"
}

如果 Chrome 采用 afterscriptexecute 事件,所有这一切都可以避免,但在此之前,我只能使用 load 事件。我提前感谢提供的任何帮助。


编辑:我已经尝试过回复中的建议:使用不同的run at 点,使用DOMContentLoaded 并附加到document.documentElement。全部都不成功,因为:1 和 2 使脚本错过了早期事件,并且 3 返回与尝试附加到 document.head 时相同的 TypeError。

脚本必须在 document.readyState = loading 时插入/运行,否则它会错过早期必要的事件,但不会太早到无法将子项附加到 的地步>documentElementhead

simpleuserscript.user.js 中的代码示例:

var script = document.createElement("script");
script.textContent = "console.log('success')";
if(document.head) {
    document.head.appendChild(script);
} else if(document.documentElement) {
    document.documentElement.appendChild(script);
}

控制台将显示 TypeError: Cannot call method 'appendChild' of null

最佳答案

Chrome 扩展 内容脚本(从 manifest.json 运行)在 document_start 运行, 确实 document.readyState Doc之前触发已达到interactive -- 这是您最早想要开始处理大多数页面元素的时间。

但是,你可以注入(inject)大部分<script>如果您愿意,请立即使用节点。只是不要 document.headdocument.body因为它们还不存在。
附加到 documentElement反而。例如:

var s = document.createElement ("script");
s.src = "http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js";
s.async = false;
document.documentElement.appendChild (s);

或者

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

如果您要添加或修改其他 DOM 元素,请在运行于 document_start 的脚本中, 等到 DOMContentLoaded像这样的事件:

document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false);

function fireContentLoadedEvent () {
    console.log ("DOMContentLoaded");
    // PUT YOUR CODE HERE.
    //document.body.textContent = "Changed this!";
}

关于javascript - Chrome 扩展设置为 `run_at` `document_start` 运行速度太快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28186349/

相关文章:

javascript - Angular2如何做一个url查询字符串

javascript - TypeError : action. Payload.map.size 不是一个函数

javascript - React组件vis-force模块报错

javascript - 是否可以直接在 Google Chrome 中运行 JS 文件并进行调试?

javascript - 扫描 html div 类以获取消息

javascript - 如何在 Ember 中没有 Controller 的情况下更改查询参数?

javascript - 如何从 Chrome 的开发控制台检查来自 REST 端点的 JSON 响应?

html - SVG 图像无法在 Chrome 上加载(有时)

javascript - chrome.downloads.download 无法从后台服务人员工作

javascript - 无需下载即可打开大尺寸pdf的方法(使用javascript上的open)