【问题标题】:document.createElement('script')... adding two scripts with one callbackdocument.createElement('script')... 用一个回调添加两个脚本
【发布时间】:2010-12-24 09:57:45
【问题描述】:

我需要添加原型,然后添加 scriptaculous 并在它们都完成加载时获得回调。我目前正在像这样加载原型:

var script = document.createElement("script");
script.src = "http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js";
script.onload = script.onreadystatechange = callback;
document.body.appendChild( script );

我可以通过链接回调来做到这一点,但这似乎是一种不好的做法(当我需要加载更多脚本时,我不想要 20 个回调方法的愚蠢链)。想法?

【问题讨论】:

  • 为什么不将这些脚本添加到 HTML 中,然后用 JavaScript 加载它?
  • 我正在制作一些代码以粘贴到其他人的 html 中以嵌入我的东西。我只想粘贴一个空的 div 和对我的 javascript 文件的引用。
  • @kdiegert:此引用粘贴在您的 js 文件中:您的意思是通过 <script src="my.js"></script>?
  • 是的,所以要粘贴的代码是:

标签: javascript dom prototypejs scriptaculous


【解决方案1】:

我建议你使用一些小型装载机,它会为你链接并做一些事情。比如这样的:

function loadScripts(array,callback){
    var loader = function(src,handler){
        var script = document.createElement("script");
        script.src = src;
        script.onload = script.onreadystatechange = function(){
            script.onreadystatechange = script.onload = null;
            handler();
        }
        var head = document.getElementsByTagName("head")[0];
        (head || document.body).appendChild( script );
    };
    (function run(){
        if(array.length!=0){
            loader(array.shift(), run);
        }else{
            callback && callback();
        }
    })();
}

这个脚本应该帮助你构建脚本标签并在所有文件加载时调用你的回调。调用非常简单:

loadScripts([
   "http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js",
   "http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js"
],function(){
    alert('All things are loaded');
});

希望这会有所帮助

【讨论】:

  • aysnc.parallel 或 async.series 可能对此有所帮助github.com/caolan/async
  • arguments.callee 在严格模式下抛出错误:From developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… "arguments.callee 不再支持。在普通代码中,arguments.callee 指的是封闭函数。这个用例很弱:简单命名封闭函数!此外,arguments.callee 实质上阻碍了内联函数等优化,因为如果访问 arguments.callee,则必须提供对未内联函数的引用。
  • @GabrielLuethje,将其更改为命名函数
  • 你能详细记录你在那里做了什么吗?
  • 这个解决方案在使用像 Ember 这样的 SinglePageApplication 时很有用。
【解决方案2】:

由于 Internet Explorer 中的错误,nemisj 的递归加载程序在 IE 中无法正常工作。可以通过在递归调用上设置延迟来解决,例如:


function loadScripts(array,callback){  
    var loader = function(src,handler){  
        var script = document.createElement("script");  
        script.src = src;  
        script.onload = script.onreadystatechange = function(){  
          script.onreadystatechange = script.onload = null;  
          if(/MSIE ([6-9]+\.\d+);/.test(navigator.userAgent))window.setTimeout(function(){handler();},8,this);  
          else handler();  
        }  
        var head = document.getElementsByTagName("head")[0];  
        (head || document.body).appendChild( script );  
    };  
    (function(){  
        if(array.length!=0){  
                loader(array.shift(),arguments.callee);  
        }else{  
                callback && callback();  
        }  
    })();  
}  

这个小技巧可以做到这一点,并且通常是 IE 中的解决方案,当出现无法解释的问题时,这种情况太常见了。

【讨论】:

    【解决方案3】:

    由于 scriptaculous 需要原型,因此您必须使用任何方法来链接侦听器来加载这些脚本。

    有多种脚本加载器可用于尽可能快地并行加载脚本,例如LABjs,但在这种情况下没有任何帮助。

    如果您最终要加载 10-20 个脚本,我建议您使用 Combiner 等工具预先组合这些脚本。

    【讨论】:

    • 实际上,这种情况正是 LABjs 旨在解决的问题。
    【解决方案4】:

    您可以承诺 script's .onload 和 .onerror 回调,然后使用 Promise.all 等待所有承诺解决,然后再继续执行依赖于这些脚本的执行。

    这是一个例子:

    const loadScript = url => 
      new Promise((resolve, reject) => {
        const script = document.createElement("script");
        script.src = url;
        script.onload = resolve;
        script.onerror = e => 
          reject(Error(`${url} failed to load`))
        ;
        document.head.appendChild(script);
      })
    ;
    
    const scriptURLs = [
      "https://unpkg.com/htm",
      "https://unpkg.com/axios@0.21.0/dist/axios.min.js",
      "https://cdnjs.cloudflare.com/ajax/libs/d3/6.3.1/d3.min.js",
      // ...
    ];
    
    Promise.all(scriptURLs.map(loadScript))
      .then(async () => {
        /* Use your scripts here */
        console.log("proving scripts loaded:");
        axios.get("http://jsonplaceholder.typicode.com/users");
        console.log(d3.csvParse("a,b\n3,4\n5,6"));
        const html = htm.bind((t, p, ...c) => ({t, p, c}));
        console.log(html`<h1 id=hello>Hello world!</h1>`);
      })
      .catch(err => console.error(err))
    ;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-15
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      • 2011-06-01
      • 2022-08-02
      相关资源
      最近更新 更多