动态脚本永远不会触发加载回调

时间:2016-06-28 15:00:36

标签: javascript

以下是我的问题的简化版本。为什么loaded回调没有被解雇?

我的目标是将一个脚本文件(我无法通过src引用)注入文档的head标记:

(function(module, scriptContent, loaded) {

    if (!window[module]) {

        var script = document.createElement('script'),
            head = document.getElementsByTagName('head')[0];

        if (script.readyState) {
            script.onreadystatechange = function() {
                if (script.readyState === 'loaded' || script.readyState === 'complete') {
                    script.onreadystatechange = null;
                    loaded();
                }
            };
        } else {
            script.onload = loaded;
        }

        script.appendChild(document.createTextNode(scriptContent));
        head.appendChild(script);
    } else {
        loaded();
    }
})('foo', 'var foo = {};', function(){
    console.log('loaded');
});

https://jsfiddle.net/on23j3wk/

1 个答案:

答案 0 :(得分:1)

因为内联脚本是同步运行的,所以不要使用readyState

这可以通过将您的'var foo = {};'更改为'console.log("b")',之前添加console.log('a')以及console.log('c')之后添加head.appendChild(script);来证明:

(function(module, scriptContent, loaded) {

    if (!window[module]) {
    	
        var script = document.createElement('script'),
            head = document.getElementsByTagName('head')[0];
            
        if (script.readyState) {
            script.onreadystatechange = function() {
                if (script.readyState === 'loaded' || script.readyState === 'complete') {
                    script.onreadystatechange = null;
                    loaded();
                }
            };
        } else {
            script.onload = loaded;
        }
        
        script.appendChild(document.createTextNode(scriptContent));
        console.log('a');
        head.appendChild(script);
        console.log('c');
    } else {
        loaded();
    }
})('foo', 'console.log("b")', function(){
	console.log('loaded');
});

请注意它们是按字母顺序记录的 如果插入的脚本是异步加载的,那么创建它的调用堆栈必须先终止,这将导致在“b”之前记录“a”和“c”。

换句话说,您可以在loaded()之后立即致电head.appendChild(script);