【问题标题】:Async Load JavaScript Files with Callback使用回调异步加载 JavaScript 文件
【发布时间】:2010-06-13 15:16:42
【问题描述】:

我正在尝试编写一个超简单的解决方案来异步加载一堆 JS 文件。到目前为止,我有以下脚本。但是,有时会在脚本未实际加载时调用回调,这会导致未找到变量错误。如果我有时刷新页面它只是工作,因为我猜文件直接来自缓存,因此比调用回调更快,这很奇怪?

var Loader = function () {

}
Loader.prototype = {
    require: function (scripts, callback) {
        this.loadCount      = 0;
        this.totalRequired  = scripts.length;
        this.callback       = callback;

        for (var i = 0; i < scripts.length; i++) {
            this.writeScript(scripts[i]);
        }
    },
    loaded: function (evt) {
        this.loadCount++;

        if (this.loadCount == this.totalRequired && typeof this.callback == 'function') this.callback.call();
    },
    writeScript: function (src) {
        var self = this;
        var s = document.createElement('script');
        s.type = "text/javascript";
        s.async = true;
        s.src = src;
        s.addEventListener('load', function (e) { self.loaded(e); }, false);
        var head = document.getElementsByTagName('head')[0];
        head.appendChild(s);
    }
}

是否有办法测试 JS 文件是否已完全加载,而不在实际的 JS 文件本身中添加任何内容,因为我想使用相同的模式来加载不受我控制的库(GMaps 等)。

调用代码,就在标记之前。

var l = new Loader();
l.require([
    "ext2.js",
    "ext1.js"], 
    function() {
        var config = new MSW.Config();
        Refraction.Application().run(MSW.ViewMapper, config);
        console.log('All Scripts Loaded');
    });

感谢您的帮助。

【问题讨论】:

  • 你在哪个浏览器和版本中测试这个?
  • 在最新的 WebKit 中,在最新的开发版 Chrome 中也是如此 :(
  • 我无法使用 Chromium 5.0.375.70 重现这一点,从 CDN 加载两个脚本,从 localhost 加载一个脚本(包含执行回调函数内的一行所需的函数)。但是async 标志真的有必要吗?如果您将s.async = true; 评论出来会怎样?
  • 是的,真正的异步只是不需要。谢谢:)
  • @galambalazs 该脚本用于移动网络应用程序,幸运的是 IE 不是问题:D

标签: javascript ajax asynchronous design-patterns


【解决方案1】:

以防万一您觉得这很有用,我创建了一个异步实用程序库,可以让您将上述代码编写为:

var Loader = function () {}

Loader.prototype = {
    require: function (scripts, callback) {
        async.map(scripts, this.writeScript, callback);
    },
    writeScript: function(src, callback) {
        var s = document.createElement('script');
        s.type = "text/javascript";
        s.src = src;
        s.addEventListener('load', function (e) { callback(null, e); }, false);
        var head = document.getElementsByTagName('head')[0];
        head.appendChild(s);
    }
}

如果您进行大量异步调用,它有一些非常强大的功能:)

http://caolanmcmahon.com/async.html

【讨论】:

    【解决方案2】:

    jQuery 怎么样....

    $.getScript('abc.js'); 
    

    以上代码将异步加载“abc.js”脚本文件....

    【讨论】:

    • 我已经在使用 xui 框架,不想再包含 jQuery 框架,它只会增加额外的重量 :) 虽然我不知道 jQuery 可以做到这一点,谢谢!
    • getScript 没有在脚本执行后调用的回调。
    【解决方案3】:

    我建议您使用像 JcorsLoader 这样的小型加载程序 javascript(仅 647B 和 Gzip)

    JcorsLoader.load(
                    "http://xxxx/jquery.min.js",
                    function() {
                        $("#demo").html("jQuery Loaded");
                    },
                    "http://xxxx/jquery.cookie.js",
                    function() {  
                        $.cookie('not_existing'); 
                    }
                );
    

    并行加载多个js并按顺序执行,不阻塞DOMReady或onload。

    https://github.com/pablomoretti/jcors-loader

    【讨论】:

      【解决方案4】:

      据我所知,您的代码没有问题,这只是 Chrome 中的一个错误(它也与 window.onload 一起使用。)

      我会将它添加到“加载”函数中触发的函数中。如果变量存在,则执行JS代码,如果不存在,则使用setTimeout在500ms左右再次检查。

      【讨论】:

      • 你也可以测试一个函数是否存在:例如,如果你想以这种方式加载 jQuery,你可以测试 $ 函数是否存在于全局范围内:if ('$' in window) /* do something */;
      • 感谢也添加了此检查 :)
      【解决方案5】:

      就像 Aaron 说的 chrome 有 bug,但 IE 和其他浏览器也有问题。

      我尝试了不同的方法来创建我的惰性加载器,但我遇到了很多问题:

      • 添加
      • 使用 ajax 读取脚本并解析文本(使用 eval,它是 javascript,所以不用担心它不是 evIl):非常难以调试(它被解析为没有 cmets 的单行,所以你不知道哪一行给出你错了)
      • 使用 ajax 读取脚本并在脚本文本中添加

      【讨论】:

        【解决方案6】:

        jcors-loader.js 无法在 Internet Explorer 中运行...

        Index.html

        <html>
            <head>
            <script type="text/javascript" src="/js/jcors-loader.js"></script>
            <script>
                JcorsLoader.load(
                        "js/jquery-1.8.0.js",
                        "/js/alertme.js",
                        function() {
                            $("#result").text("TEST OK");
                        }
                );
        
            </script>
            </head>
            <body>
            <h1 id="result"></h1>
            </body>
            </html>
        

        alertme.js

        alert("加载");

        这在 chrome 和 firefox 中运行良好,它显示“TEST OK”并弹出...但在 IE(7,8,9) 中没有消息或警报...任何帮助将不胜感激。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-17
          • 1970-01-01
          • 1970-01-01
          • 2012-11-24
          • 2012-10-11
          • 2012-10-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多