可以信任script.readyState来检测动态脚本加载的结束吗?

Eri*_*ier 31 javascript scripting load dynamic labjs

我使用动态脚本加载来减少初始页面加载的持续时间.为确保可以访问脚本定义的函数和对象,我需要确保脚本已完全加载.

为此我开发了自己的Javascript库,因此对该主题进行了大量研究,研究了它在不同库中的完成情况.在与此问题相关的讨论中,LABjs的作者Kyle Simpson 表示:

LABjs(以及许多其他加载器)在所有脚本元素上设置"onload"和"onreadystatechange",知道某些浏览器会触发一个,有些浏览器会触发另一个...

撰写本文时,您可以在当前版本的jQuery中找到此示例,v1.3.2:

// Attach handlers for all browsers
script.onload = script.onreadystatechange = function(){
    if ( !done && (!this.readyState ||
    this.readyState == "loaded" || this.readyState == "complete") ) {
        done = true;
        success();
        complete();

        // Handle memory leak in IE
        script.onload = script.onreadystatechange = null;
        head.removeChild( script );
    }
};
Run Code Online (Sandbox Code Playgroud)

这是最先进的技术,但在分析Opera 9.64中的一个奇怪的行为时,我得出的结论是,使用这种技术,onload回调过早被解雇了.

我会在回答这个问题时发表自己的研究结果,并希望收集社区的进一步证据和反馈.

Eri*_*ier 8

在Opera中,script.readyState属性不可信任.例如,在脚本在Opera 9.64中运行之前,可能会触发readyState"loaded".

我在Opera 9.64和Opera 10中执行了相同的测试,结果不同.

在Opera 9.64中,onreadystatechange处理程序在脚本运行之前和之后一次被触发两次.readyState属性在两种情况下都被"加载",这意味着无法信任此值来检测脚本加载的结束:

# Fri Dec 18 2009 17:54:43 GMT+0100
# Opera/9.64 (Windows NT 5.1; U; en) Presto/2.1.1
Test for script.readyState behavior started
Added script with onreadystatechange handler
readystatechange: loaded
test1.js: Start
test1.js: Start of closure
test1.js: End of closure
readystatechange: loaded
Run Code Online (Sandbox Code Playgroud)

在Opera 10中,onreadystatechange处理程序仍然使用值"loaded"触发两次,但是在脚本运行后的两次:

# Fri Dec 18 2009 18:09:58 GMT+0100
# Opera/9.80 (Windows NT 5.1; U; en) Presto/2.2.15 Version/10.10
Test for script.readyState behavior started
Added script with onreadystatechange handler
test1.js: Start
test1.js: Start of closure
test1.js: End of closure
readystatechange: loaded
readystatechange: loaded
Run Code Online (Sandbox Code Playgroud)

这些不同的行为表明onreadystatechange不是检测Opera中脚本加载结束的可靠方法.由于Opera还支持onload侦听器,因此应该使用其他机制.

根据这些测试的结果,onreadystatechange只应用于检测Internet Explorer中脚本加载的结束,不应在其他浏览器中设置.

  • @Justin Johnson看起来很尴尬,你会算上"装满"的事件,但只是在Opera? (2认同)