javascript - 动态脚本加载同步

标签 javascript

我有一个脚本,它知道动态加载包含 javascript 类的脚本。 我正在使用以下代码加载类脚本:

var head = document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "myscript.js";
head.appendChild(script);

然后我尝试使用 eval 创建新类:

var classObj = eval(" new MyClass()" );

问题是,在脚本加载到内存之前,正在执行 eval 的代码,并且我收到一条错误,指出 MyClass 未定义。

有办法同步这些事件吗?我需要确保脚本已完全加载到内存中,然后才能开始从中分配类。

最佳答案

您需要将事件处理程序附加到 onload 方法(在符合 Web 标准的浏览器中)或 onreadystatechange,在 Internet Explorer 中检查 script.readyState 属性是否等于“已加载”或“完成”。

在收到脚本已加载的通知之前,您可能正在尝试访问尚未声明或创建的对象、函数和属性。

这是一个示例函数,从模块 bezen.dom.js 中提取在我的Javascript library, bezen.org :

var appendScript = function(parent, scriptElt, listener) {
    // append a script element as last child in parent and configure 
    // provided listener function for the script load event
    //
    // params:
    //   parent - (DOM element) (!nil) the parent node to append the script to
    //   scriptElt - (DOM element) (!nil) a new script element 
    //   listener - (function) (!nil) listener function for script load event
    //
    // Notes:
    //   - in IE, the load event is simulated by setting an intermediate 
    //     listener to onreadystate which filters events and fires the
    //     callback just once when the state is "loaded" or "complete"
    //
    //   - Opera supports both readyState and onload, but does not behave in
    //     the exact same way as IE for readyState, e.g. "loaded" may be
    //     reached before the script runs.

    var safelistener = catchError(listener,'script.onload');

    // Opera has readyState too, but does not behave in a consistent way
    if (scriptElt.readyState && scriptElt.onload!==null) {
      // IE only (onload===undefined) not Opera (onload===null)
      scriptElt.onreadystatechange = function() {
        if ( scriptElt.readyState === "loaded" || 
             scriptElt.readyState === "complete" ) {
          // Avoid memory leaks (and duplicate call to callback) in IE
          scriptElt.onreadystatechange = null;
          safelistener();
        }
      };
    } else {
      // other browsers (DOM Level 0)
      scriptElt.onload = safelistener;
    }
    parent.appendChild( scriptElt );
};

为了适应您的需要,您可以替换对 catchError 的调用,它包装监听器以捕获和记录错误,并使用修改后的函数:

var appendScript = function(parent, scriptElt, listener) {
    // append a script element as last child in parent and configure 
    // provided listener function for the script load event
    //
    // params:
    //   parent - (DOM element) (!nil) the parent node to append the script to
    //   scriptElt - (DOM element) (!nil) a new script element 
    //   listener - (function) (!nil) listener function for script load event
    //
    // Notes:
    //   - in IE, the load event is simulated by setting an intermediate 
    //     listener to onreadystate which filters events and fires the
    //     callback just once when the state is "loaded" or "complete"
    //
    //   - Opera supports both readyState and onload, but does not behave in
    //     the exact same way as IE for readyState, e.g. "loaded" may be
    //     reached before the script runs.

    var safelistener = function(){
      try {
        listener();
      } catch(e) {
        // do something with the error
      }
    };

    // Opera has readyState too, but does not behave in a consistent way
    if (scriptElt.readyState && scriptElt.onload!==null) {
      // IE only (onload===undefined) not Opera (onload===null)
      scriptElt.onreadystatechange = function() {
        if ( scriptElt.readyState === "loaded" || 
             scriptElt.readyState === "complete" ) {
          // Avoid memory leaks (and duplicate call to callback) in IE
          scriptElt.onreadystatechange = null;
          safelistener();
        }
      };
    } else {
      // other browsers (DOM Level 0)
      scriptElt.onload = safelistener;
    }
    parent.appendChild( scriptElt );
};

关于javascript - 动态脚本加载同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2321204/

相关文章:

javascript - 图表.js : Controller for Scatter chart doesn't work for draw function

javascript - 如何创建带圆 Angular 的图表?

javascript - 计算递减值的算法,接近极限

javascript - 汇总对象数组并计算每个唯一对象名称的平均值

javascript - 在 JavaScript 中从 HTML 源代码中提取 JSON

JavaScript - 为什么设置原型(prototype)原型(prototype)不起作用?

javascript - window.onload 与 $(document).ready()

javascript - 将值添加到 y :axis if all the values are Zero after filtering

javascript - D3 图形事件监听器之外的任何地方

javascript - 当我进入源代码 View 时,如何跳转到 CKEditor 4 中的当前位置?