正在编写 Javascript 库:异步加载计时问题

Writing Javascript library: Asynch load timing issue

在我正在编写的 JS 库中,我有这个 loadScript func:

function loadScript(src, callback) {
  var script = document.createElement('script');
  script.src = src;
  // script.type = "text/javascript";
  // script.async = false;
  if (typeof callback !== 'undefined') {
    script.onload = function () {
      callback();
    };
  }
  document.head.appendChild(script);
}

在主js文件中,我用它在主js文件加载后动态加载依赖项,在其回调中初始化JSLib对象。

  loadScript(baseUrl + '/dependencies/you-load-me-long-time.js', function() {
     window.JSLib = true;
   }

然后我有一个调用这个库的网页。

var jsLib = new JSLib({...});

我遇到的问题是——在加载这个JS库的网页中,浏览器报错JSLib未定义,因为依赖文件you-load-me-long-time.js还没有加载完成当执行网页中的脚本时。

目前似乎有效的解决方法是,在网页中,我将启动代码包装在 $(window).load(function() {}); 调用中。

有什么方法可以解决这个时间问题吗?例如:"blocking" 加载网页的其余部分,直到加载 JSLib(无论如何听起来都不是个好主意),等等...

只有两种方法可以创建通过 JS 加载的阻塞式动态脚本,而这两种方法都不太受欢迎。

  1. 如果文档还在解析中,可以使用document.write()在当前文档位置插入一个<script>标签。然后将同步解析和加载。

  2. 如果脚本资源与文档同源,您可以使用同步 Ajax 调用获取脚本,然后评估脚本。

由于这些都不是特别可取的,通常的解决方法是将回调一直返回给脚本的调用者,以便他们可以在异步操作完成时参与并将他们的代码放入那个异步回调。

var jsLib = new JSLib({...}, function() {
    // put code here that uses the jsLib because now it is loaded
});

由于这个混乱的原因,将构造函数的完成作为异步操作通常不是一个好习惯。它使对象的使用变得非常复杂。

更常见的做法是让构造函数只创建对象的 shell,然后需要调用 .load(fn) 方法来实际加载它。这可能会减少调用者滥用库的机会。

var jsLib = new JSLib({....});
jsLib.load(function(err) {
    if (err) {
        // error loading the library
    }  else {
        // library is loaded now and all functionality can be used
    }
});

仅供参考,您使用 $(window).load() 的想法不是一个好主意。该方法可能会意外地工作,因为它会延迟足够的时间直到您的脚本恰好被加载,但是 window load 事件不会专门等待动态加载的脚本被加载,因此它不是等待的可靠方法你的脚本。