如何检测脚本是否已加载*和*在chrome扩展中执行?

sro*_*sey 5 google-chrome google-chrome-extension google-chrome-devtools

我已经追踪了几天的bug ...然后我意识到这个bug就是我.:/

我一直在使用webRequest.onComplete,过滤脚本.我的错误是我在加载和执行的脚本之间建立了错误的关联.get以不同于它们执行的顺序加载,因此事件的时间顺序不符合我需要它的顺序.我需要在某些脚本之间注入,所以我需要在文件执行之后和之前需要一个事件下一个.

我现在能想到的唯一解决方案是在执行之前更改正在加载的JS.但它让我的胃转了.bfcache会造成更大的破坏,所以也不是一个好的解决方案.

我会使用HTML5规范的afterscriptexecute,但这不是在Chrome中实现的.是否有其他API,也许是我可以使用的扩展API?

Rob*_*b W 8

注意:此方法不再适用于Chrome 36.没有直接的选择.

注意:以下答案仅适用于外部脚本,即加载的脚本<script src>.

在Chrome(和Safari)中,"beforeload"事件在加载资源之前触发.此事件允许用户阻止资源,因此永远不会获取脚本.在这种情况下,您可以确定加载的资源是否是脚本,并检查是否要执行某些操作

此事件可用于模拟beforescriptexecute/afterscriptexecute:

document.addEventListener('beforeload', function(event) {
    var target = event.target;
    if (target.nodeName.toUpperCase() !== 'SCRIPT') return;
    var dispatchEvent = function(name, bubbles, cancelable) {
        var evt = new CustomEvent(name, {
            bubbles: bubbles,
            cancelable: cancelable
        });
        target.dispatchEvent(evt);
        if (evt.defaultPrevented) {
            event.preventDefault();
        }
    };
    var onload = function() {
        cleanup();
        dispatchEvent('afterscriptexecute', true, false);
    };
    var cleanup = function() {
        target.removeEventListener('load', onload, true);
        target.removeEventListener('error', cleanup, true);
    }
    target.addEventListener('error', cleanup, true);
    target.addEventListener('load', onload, true);

    dispatchEvent('beforescriptexecute', true, true);
}, true);
Run Code Online (Sandbox Code Playgroud)

发货时间与原始发货时间不完全相同,但对大多数情况来说已足够.这是(非模拟)事件的时间线:

beforeload             Before the network request is started
beforescriptexecute    Before a script executes
afterscriptexecute     After a script executes
onload                 After the script has executed
Run Code Online (Sandbox Code Playgroud)

这是一种简单的方法,可以看到事件按预期工作:

window.addEventListener('afterscriptexecute', function() {
    alert(window.x);
});
document.head.appendChild(document.createElement('script')).src = 'data:,x=1';
document.head.appendChild(document.createElement('script')).src = 'data:,x=2';
Run Code Online (Sandbox Code Playgroud)

该演示可以在http://jsfiddle.net/sDaZt/上看到