【问题标题】:How to get a content script to load AFTER a page's Javascript has executed?如何在页面的 Javascript 执行后加载内容脚本?
【发布时间】:2012-12-04 17:15:48
【问题描述】:

我的扩展应该加载一个内容脚本,searchTopic.js,只有在它注入的页面已经完全加载之后(是的,我在扩展清单中将“run_at”设置为“document_end”),但实际上它在创建所有 DOM 对象之前加载(关键的对象是通过页面中的一些 Javascript 创建的)。所以,问题是,我怎样才能等到页面的 Javascript 执行完毕?这是我的清单:

"content_scripts": [
  {
  "run_at": "document_end",
  "matches": ["https://groups.google.com/forum/*"],
  "js": ["searchTopic.js"]
  }
],

【问题讨论】:

  • 你无法预测未来。您找到的任何解决方案都特定于您编写脚本的情况。尝试使用window.onload 事件,或者通过一种使用计时器的轮询来检测页面何时处于所需状态。
  • 您无法知道所有 javascript 何时会执行完毕。它在解析时运行一次,但它的操作(DOM 操作,进一步的脚本加载)可能会在稍后发生,由任何事件触发 - 我担心这些对你来说很有趣。

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


【解决方案1】:

你使用 window.load 方法。

function addLoadEvent(a) {
    var b = window.onload;
    "function" != typeof window.onload ? window.onload = a : window.onload = function () {
        b && b(),
            a()
    }
}
function init() {
    alert('init');
}
addLoadEvent(init);

【讨论】:

    【解决方案2】:

    "run_at": "document_end" is the equivalent to DOMContentLoaded. 也就是说,它在 static HTML 加载之后,但在慢速图像和慢速完成 javascript 之前触发。

    因此,您不能仅通过单独设置清单来设置内容脚本在页面的 JS 之后触发。您必须在内容脚本本身中为此编写代码。

    对于内容脚本,"run_at": "document_end" 将在 onload 事件之前触发(与默认的 document_idle 不同——它可以在不可预知的时间触发)。

    因此,第一步是在您的内容脚本 (searchTopic.js) 中使用类似这样的代码等待 load 事件:

    window.addEventListener ("load", myMain, false);
    
    function myMain (evt) {
        // DO YOUR STUFF HERE.
    }
    


    如果您关心的脚本需要一段时间才能完成,您将不得不根据具体情况轮询某些条件。例如:

    window.addEventListener ("load", myMain, false);
    
    function myMain (evt) {
        var jsInitChecktimer = setInterval (checkForJS_Finish, 111);
    
        function checkForJS_Finish () {
            if (    typeof SOME_GLOBAL_VAR != "undefined"
                ||  document.querySelector ("SOME_INDICATOR_NODE_css_SELECTOR")
            ) {
                clearInterval (jsInitChecktimer);
                // DO YOUR STUFF HERE.
            }
        }
    }
    

    【讨论】:

    • 这是问题所在:我正在查看的页面 (groups.google.com/forum/?fromgroups=#!searchin/…) 没有任何可预测的条件进行轮询;至少,我找不到。
    • 顺便说一句,答案 #1 和 2 发生了什么?
    • 确实有这样的条件,否则你不能说searchTopic.js加载得太早了。您究竟要做什么,以及您在控制台上收到什么错误消息(如果有)。 ...您是什么意思“答案#1和2”?该问题的其中一个答案已被其海报删除。它没有解决您的问题。
    • @HaveAGuess,是的,它们(通常)会起作用,但在实践中它们经常会变得棘手。一个更简单的计时器每次都能工作,更强大,更便携。
    • +1 用于计时器建议。在尝试了变异观察者方法之后,我可以证明它变得很棘手。
    【解决方案3】:

    script 元素按顺序执行。如果body 中有script 节点,浏览器甚至会停止加载DOM 内容。这保证可以工作,否则document.write() 将停止工作。

    所以你有两个解决方案:

    1. 使用onload 事件加载您的代码。
    2. 添加一个脚本标记作为页面的最后一个元素(body 元素中的最后一个元素)。此脚本将在所有其他脚本完成后执行并且在正文已转换为 DOM 树后执行。

    【讨论】:

    • 脚本元素可以是deferred or asynch。或者脚本可以动态加载。或者可以加载脚本,但包含/链接的代码需要一些时间才能完成初始化。
    • window.onload 等待 async/defer 脚本加载和执行,这样比在页面底部添加脚本效果更好。 (请参阅W3C's HTML API 上的“The download of an external script must delay the load event.”。)等待异步脚本行为(Ajax、setTimeout、事件)的一般问题仍然存在,但这不能以一般方式解决.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-02
    • 2012-02-18
    • 2012-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多