动态脚本加载同步

Ami*_*mir 10 javascript

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

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

我正在尝试使用eval创建新类:

var classObj = eval(" new MyClass()" );
Run Code Online (Sandbox Code Playgroud)

问题是eval的代码正在执行bofre脚本已加载到内存中我得到一个错误, MyClass is undefined.

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

Eri*_*ier 5

您需要在onload方法中,在符合Web标准的浏览器或onreadystatechange中附加事件处理程序,在Internet Explorer中检查script.readyState属性是否等于"loaded"或"complete".

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

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

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 );
};
Run Code Online (Sandbox Code Playgroud)

为了使其适应您的需要,您可以替换对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 );
};
Run Code Online (Sandbox Code Playgroud)


Rob*_*Rob 0

您确定<script>向 DOM 添加元素会导致浏览器真正评估脚本吗?我模糊地记得在某处读过,但没有,但也许我昨天吸入了太多烤箱清洁剂。