简体   繁体   English

设置为`run_at``document_start`的Chrome扩展程序运行得太快了?

[英]Chrome extension set to `run_at` `document_start` is running too fast?

EDIT: Something was wrong with my Chrome browser and creating a conflict with my script, a full reinstall eliminated whatever the problem source was. 编辑:我的Chrome浏览器出现问题并与我的脚本产生冲突,无论问题来源是什么,都可以完全重新安装。 If I happen to find out what was causing it I will include it in here. 如果我碰巧找出导致它的原因,我会把它包含在这里。

EDIT2: Just to let anyone reading this in 2017 know that I haven't forgotten this and I have never had this problem since my previous edit. 编辑2:只是为了让在2017年阅读此内容的人知道我没有忘记这一点,自从我之前的编辑以来我从未遇到过这个问题。

EDIT3: It is 2019 and so far I've never had this problem again. 编辑3:这是2019年,到目前为止,我再也没遇到过这个问题。


I have been learning how to create a simple Chrome extension which is a userscript port. 我一直在学习如何创建一个简单的Chrome扩展程序,这是一个用户脚本端口。 The script works perfectly with Tampermonkey with the setting run at to document-start , all the necessary events that need to be caught from the beginning are all captured. 该脚本与Tampermonkey完美配合,设置run atdocument-start ,所有需要document-start捕获的必要事件都被捕获。

However, when I set the same settings in the Chrome extension I discovered that the same running setting is faster than Tampermonkey's which causes the first function to fail: ( Uncaught TypeError: Cannot call method 'appendChild' of null. ) since it tries to append a script element to the head section, which doesn't exist until 0.010s later. 但是,当我在Chrome扩展程序中设置相同的设置时,我发现相同的运行设置比Tampermonkey更快,导致第一个函数失败:( Uncaught TypeError: Cannot call method 'appendChild' of null. )因为它试图追加head部分的脚本元素,直到0.010s后才存在。

My dirty solution so far has been to make use of a setInterval function with the timer set to 10 to check if document.head exists and then proceed with the code if the condition is true. 到目前为止,我的脏解决方案是使用setInterval函数,将计时器设置为10来检查document.head存在,然后在条件为真时继续执行代码。

Is there any way that I can make this work correctly without having to resort to setInterval or maybe replicate Tampermonkey's grant none option which appears to run the userscript on the webpage context? 有没有什么方法可以让我正确地工作,而不必诉诸于setInterval或者可能复制Tampermonkey的grant none选项,它似乎在网页上下文中运行用户脚本?

The following is my manifest.json file: 以下是我的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"
}

All of this could be avoided if Chrome would adopt the afterscriptexecute event, but until that happens I am stuck with the load event. 如果Chrome会采用afterscriptexecute事件,所有这一切都可以避免,但在此之前我会遇到load事件。 I thank in advance any help provided. 我提前感谢你提供的任何帮助。


EDIT: I have already tried the suggestions in the replies: using a different run at point, using DOMContentLoaded and append to document.documentElement . 编辑:我已经尝试了回复中的建议:使用不同的run at点,使用DOMContentLoaded加到document.documentElement All were unsuccessful because: 1 and 2 makes the script miss early events, and 3 returns the same TypeError as when trying to append to document.head . 所有都不成功,因为:1和2使脚本错过早期事件,3返回与尝试追加到document.head时相同的TypeError。

The script has to be inserted/running when document.readyState = loading or else it will miss early necessary events, but not so early to the point of being unable to append childs to either documentElement or head document.readyState = loading时,必须插入/运行该脚本,否则它将错过早期必要事件,但不能太早到无法将子项附加到documentElementhead

An example of the code inside simpleuserscript.user.js : simpleuserscript.user.js中的代码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);
}

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

Chrome extension Content scripts (run from a manifest.json ) that are run at document_start , do fire before document.readyState Doc has reached interactive -- which is the earliest you want to start messing with most page elements. Chrome扩展内容的脚本 (从运行manifest.json是在运行) document_start火之前document.readyState 文件已经达到interactive -这是你要开始与大多数网页元素搞乱最早的。

However, you can inject most <script> nodes right away if you wish. 但是,如果您愿意,可以立即注入大多数<script>节点。 Just not to document.head or document.body because they don't exist yet. 只是不要document.headdocument.body因为它们还不存在。
Append to documentElement instead. 追加到documentElement For example: 例如:

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);

Or 要么

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

If you are adding or modifying other DOM elements, in a script running at document_start , wait until the DOMContentLoaded event like so: 如果要添加或修改其他 DOM元素,请在运行document_start的脚本中等待DOMContentLoaded事件,如下所示:

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

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

Your problem is that, when using "run_at": "document_start" , the only element that is granted to exist in the DOM is the <html> element. 您的问题是,当使用"run_at": "document_start" ,DOM中唯一被授予的元素是<html>元素。 If you want to avoid errors relative to page load, like trying to access some element that hasn't been created yet, you'll have to either: 如果你想避免相对于页面加载的错误,比如试图访问一些尚未创建的元素,你将不得不:

  • Make your script run at "document_idle" or "document_end" . 使您的脚本在"document_idle""document_end" Although "document_end" still doesn't grant you that all the elements and resources of the page have been fully loaded (but the DOM has already been parsed), the "document_idle" keyword will give you the certainty that the DOM has been parsed and all the elements and resources have been loaded properly before your script runs. 虽然"document_end"仍然没有授予您页面的所有元素和资源都已完全加载(但DOM已经被解析),但"document_idle"关键字将确保DOM已被解析并且在脚本运行之前已正确加载所有元素和资源。

  • Or, instead, you can continue using "document_start" wrapping your code inside a "DOMContentLoaded" listener, which will make it run when the DOM has completely finished loading and parsing, similarly to "document_idle" . 或者,您可以继续使用"document_start"将代码包装在"DOMContentLoaded"侦听器中,这将使DOM在完全加载和解析时运行,类似于"document_idle" Here's an example: 这是一个例子:

     document.addEventListener("DOMContentLoaded", function() { // Run your code here... }); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 通过run_at document_start传递的Google Chrome扩展程序消息 - Google Chrome Extension message passing with run_at document_start chrome扩展程序:尽管运行了at:document_idle,js脚本仍过早触发 - chrome extension: the js script fires too early despite run_at: document_idle Chrome扩展程序-在“ document_start”之前获取变量值 - Chrome extension - get variable value before “document_start” 我注入的<script>在目标页面的javascript之后运行,尽管使用了run_at:document_start? - My injected <script> runs after the target-page's javascript, despite using run_at: document_start? document_start 和 document_end 处的 Chrome 扩展 content_script - Chrome Extension content_script at both document_start and document_end 在使用Chrome扩展程序加载之前,使用document_start修改文档html - Modify document html before load with Chrome extension, using document_start Chrome 扩展内容脚本 javascript - run_at document_end 无法正常工作 - Chrome extension content-script javascript - run_at document_end not working correctly 无法获取Chrome扩展内容脚本(document_start)以将同步第三方脚本注入 <head> 块 - Can't get Chrome extension content script (document_start) to inject synchronous third-party script into <head> block 在&#39;document_start&#39;上运行的内容脚本会阻止网页上的JS脚本吗? - Content script run at 'document_start' blocks the JS scripts on the web page? Chrome扩展程序未在文档开始时运行脚本并且未打印内容 - Chrome Extension not running scripts on document start and not printing content
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM