Chrome扩展设置为`run_at`` document_start`运行速度过快? [英] Chrome extension set to `run_at` `document_start` is running too fast?

查看:5647
本文介绍了Chrome扩展设置为`run_at`` document_start`运行速度过快?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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






我一直在学习如何创建一个简单的Chrome扩展,是一个userscript端口。该脚本与Tampermonkey完美配合,设置运行于 document-start ,所有需要的必要事件但是,当我在Chrome扩展中设置相同的设置时,我发现相同的运行设置比Tampermonkey更快,因为它导致第一个函数失败:(未捕获的TypeError:无法调用null的方法'appendChild'),因为它试图将脚本元素追加到部分,直到0.010s后才存在。



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



有没有什么办法可以使这个工作正常,而不必诉诸 setInterval 或者可能复制Tampermonkey的授予非e 选项似乎在网页上下文中运行userscript



以下是我的manifest.json文件:


$ b $

  {
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扩展程序,
name:Testing,
version:1
}

如果Chrome会采用 afterscriptexecute 事件,但直到发生这种情况时,我停留在 load 事件中。我提前感谢提供的任何帮助。




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



脚本必须在 document.readyState = loading 时插入/运行,否则它将错过早期必要的事件,但不会太早无法将孩子追加到 documentElement 头部



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:Can not call method'appendChild 'of null

解决方案

Chrome扩展程序内容脚本 document_start do document.readyState 文档 已达到交互式 - 这是您想要开始处理大多数页面元素的最早阶段。



然而,如果你愿意,你可以立即注入大多数< script> 节点。只是不要 document.head document.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);






如果要添加或修改其他其他在运行于 document_start 的脚本中的DOM元素,等到 DOMContentLoaded 事件如此: p>

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

function fireContentLoadedEvent(){
console.log(DOMContentLoaded);
//在此放置您的代码。
//document.body.textContent =更改了这个!;
}


EDIT: Something was wrong with my Chrome browser and creating a conflict with my script, a full reinstall eliminated whatever the problem source was. 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.


I have been learning how to create a simple Chrome extension which is a userscript port. 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.

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.

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.

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?

The following is my manifest.json file:

{
    "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. 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. 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.

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 documentElementor head

An example of the code inside 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

解决方案

Chrome extension Content scripts (run from a manifest.json) that are run at document_start, do fire before document.readyStateDoc has reached interactive -- which is the earliest you want to start messing with most page elements.

However, you can inject most <script> nodes right away if you wish. Just not to document.head or document.body because they don't exist yet.
Append to documentElement instead. 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:

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

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

这篇关于Chrome扩展设置为`run_at`` document_start`运行速度过快?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆