如何检测javascript文件是否已加载?

IT技术 javascript jquery
2021-02-02 07:55:54

加载 JavaScript 文件时是否会触发事件?问题出现是因为 YSlow 建议将 JavaScript 文件移动到页面底部。这意味着 $(document).ready(function1)function1加载包含代码的 js 文件之前触发

如何避免这种情况?

6个回答

我没有方便的参考,但是脚本标签是按顺序处理的,所以如果你把你$(document).ready(function1)的脚本标签放在定义函数1等的脚本标签之后,你应该很高兴。

<script type='text/javascript' src='...'></script>
<script type='text/javascript' src='...'></script>
<script type='text/javascript'>
$(document).ready(function1);
</script>

当然,另一种方法是通过组合文件作为构建过程的一部分来确保您总共只使用一个脚本标记。(除非你从某个地方的 CDN 加载其他的。)这也将有助于提高页面的感知速度。

编辑:刚刚意识到我实际上并没有回答您的问题:我认为没有触发跨浏览器事件,不。 如果您足够努力,请参见下文。您可以测试符号并使用 setTimeout 重新安排:

<script type='text/javascript'>
function fireWhenReady() {
    if (typeof function1 != 'undefined') {
        function1();
    }
    else {
        setTimeout(fireWhenReady, 100);
    }
}
$(document).ready(fireWhenReady);
</script>

...但如果您的脚本标记顺序正确,则不必这样做。


更新:script如果您愿意,您可以获得动态添加到页面的元素的加载通知要获得广泛的浏览器支持,您必须做两件不同的事情,但作为一种组合技术,这是有效的:

function loadScript(path, callback) {

    var done = false;
    var scr = document.createElement('script');

    scr.onload = handleLoad;
    scr.onreadystatechange = handleReadyStateChange;
    scr.onerror = handleError;
    scr.src = path;
    document.body.appendChild(scr);

    function handleLoad() {
        if (!done) {
            done = true;
            callback(path, "ok");
        }
    }

    function handleReadyStateChange() {
        var state;

        if (!done) {
            state = scr.readyState;
            if (state === "complete") {
                handleLoad();
            }
        }
    }
    function handleError() {
        if (!done) {
            done = true;
            callback(path, "error");
        }
    }
}

根据我的经验,错误通知 ( onerror) 不是 100% 跨浏览器可靠的。另请注意,某些浏览器会同时执行这两种机制,因此该done变量可以避免重复通知。

后?我没有跟着你。
2021-03-16 07:55:54
@Steverino:不,除非您使用asyncdefer属性来改变事物,否则scriptHTML 中的标签会使页面加载停止,直到脚本代码运行(因为它可能会输出带有 的东西document.write),所以您肯定知道较早的script已在较晚的之前加载(或失败)。(浏览器很乐意并行下载脚本,但它们确保它们按 HTML 中的顺序执行。)asyncdefer更改它。请参阅:html.spec.whatwg.org/multipage/scripting.html#attr-script-async
2021-03-22 07:55:54
对于动态加载器,您忘记了 appendChild。不过还是很棒的代码。
2021-03-24 07:55:54
这很好,但如果你使用 jQuery,也可以考虑$.getScript() api.jquery.com/jQuery.getScript
2021-03-25 07:55:54
感谢您的回答,但对我来说似乎有点奇怪为什么我应该在 <script> 标签之后放置 $(document).ready(...) 。
2021-04-12 07:55:54

当他们说“页面底部”时,他们的意思并不是字面上的底部:他们的意思是在结束</body>标记之前将脚本放在那里,它们将在 DOMReady 事件之前加载;之后放置它们,DOM 将在加载它们之前准备好(因为在</html>解析结束标记时它已经完成),正如您发现的那样,这将不起作用。

如果你想知道我怎么知道这就是他们的意思:我曾在雅虎工作过!我们把我们的脚本放在</body>标签之前:-)

编辑:另外,请参阅 TJ Crowder 的回复并确保您按正确的顺序排列。

看看 jQuery 的 .load() http://api.jquery.com/load-event/

$('script').load(function () { }); 
:) 有时有用的功能
2021-04-13 07:55:54

除了@TJ Crowder 的回答之外,我还添加了一个递归外循环,允许遍历数组中的所有脚本,然后在加载所有脚本后执行一个函数:

loadList([array of scripts], 0, function(){// do your post-scriptload stuff})

function loadList(list, i, callback)
{
    {
        loadScript(list[i], function()
        {
            if(i < list.length-1)
            {
                loadList(list, i+1, callback);  
            }
            else
            {
                callback();
            }
        })
    }
}

当然,如果您愿意,您可以制作一个包装器来摆脱“0”:

function prettyLoadList(list, callback)
{
    loadList(list, 0, callback);
}

干得好@TJ Crowder - 我对我在其他线程中看到的“在运行回调之前添加几秒钟的延迟”感到畏缩。

我总是从 JavaScript 文件的末尾调用来注册它的加载,它曾经对我来说非常适合所有浏览器。

例如:我有一个 index.htm、Js1.js 和 Js2.js。我在 index.htm 标头中添加了函数 IAmReady(Id) 并使用文件末尾的参数 1 和 2 调用它,分别是 Js1 和 Js2。一旦 IAmReady 函数从两个 js 文件中获得两次调用(将调用次数存储在静态/全局变量中),它就会有一个运行启动代码的逻辑。