javascript - 控制动态加载脚本的加载顺序

标签 javascript coffeescript

我有一个基本的SPA它按需加载一些资源(主要是样式表和脚本)。

加载器看起来像这样(这是一个简化版本):

class ModuleXLoader
    constructor: ->
        @scripts = [
            'https://www.example.com/assets/js/script1.js',
            'https://www.example.net/assets/js/script2.js',
            'https://www.example.org/assets/js/script3.js'
        ]
        @scriptsLoaded = 0

    load: (@callback) ->
        document.head.appendChild @.scriptTag url for url in @scripts

    scriptTag: (url) ->
        domElement = document.createElement 'script'
        domElement.type = 'text/javascript'
        domElement.onload = (event) =>
            console.log event.currentTarget.src # This logs the script's URL
            @.callback() if ++@scriptsLoaded is @scripts.length and typeof @callback is 'function'
        domElement.src = url
        return domElement

所以,当我需要加载ModuleX时我愿意:

loader = new ModuleXLoader()
loader.load () =>
   console.log 'All scripts have been loaded, let\'s do stuff!' 

这会将所需的脚本附加到我的 <head>一切都按预期进行。

<小时/>

当所需脚本之间存在某些依赖关系时,就会出现问题。根据每个 CDN 的响应时间(假设 example.comexample.net ...)脚本以随机顺序加载,因此,有时我会得到经典的:

Uncaught ReferenceError: ModuleXDependency is not defined

当然,我在我的 @scripts 上尝试了不同的排序。数组,但这并不重要。

我正在考虑某种信号量实现:

@scripts =
    script1:
        url: 'https://www.example.com/assets/js/script1.js'
        requires: 'script3'
        loaded: false
    script2: # etc.


domElement.onload = (event) =>
    # This is not a real implementation but kind of pseudocode idea...
    @wait() while not @scripts[@scripts['script1'].requires].loaded

但说实话,这样走感觉太脏了,所以我想知道是否有人有更好的主意......

最佳答案

我的建议是使用像 AMD 这样的模块定义。也许您应该考虑使用现有的模块加载器,例如 requirejs 。您还可以在这里找到有关 AMD 的文档。也许阅读 whyAMD文本。

如果您想要一个绝对最小的加载程序并自己加载脚本,您可以查看 loader.js .

AMD 的想法基本上是这样定义模块:

define('dep', [], function() {
  // here goes your code
  return {};
});

define('mymodule', ['dep'], function(dep) {
  // here goes your code.
});

loader.jsrequire.js 这样的加载器基本上会构建这些模块的图表,然后当你执行类似 require('mymodule ') 它会知道必须先调用 dep,然后将结果作为第一个参数注入(inject)到 mymodule 中。

loader.js 基本上只会执行此操作,而 require.js 具有通过网络加载模块的能力。

但是,对于这两种方法,您都可以手动加载脚本标记,等到所有标记都加载完毕,然后调用您的入口点。

重要的是,对 define 的调用执行顺序并不重要。

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

相关文章:

coffeescript - 根据元素的奇数/偶数位置转换数组

javascript - 表排序器排序和过滤不起作用

javascript - 跨多个 View 使用的主干事件

javascript - js2咖啡: command not found

backbone.js - MarionetteJS : Render only after fetch model success

javascript - 为什么在这个 CoffeeScript 中使用 if 语句

javascript - 有没有办法通过属性获取元素xml?

javascript - 如何使用 jQuery 访问 AJAX 中的 JSON 对象?

javascript - AJAX 在单个 Highcharts 图表中显示来自两个不同函数的值,而不是两个不同的值

JavaScript 历史后退/前进