首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何按特定顺序动态加载多个脚本?

如何按特定顺序动态加载多个脚本?
EN

Stack Overflow用户
提问于 2019-04-09 22:59:43
回答 2查看 1.4K关注 0票数 1

我需要动态加载x脚本(假设本例为6)(在TypeScript和JavaScript中)。

前两个脚本由最后4个脚本使用,所以我必须确保脚本1和脚本2在加载最后4个脚本之前已经加载。

代码语言:javascript
运行
复制
var scripts = [
  { "path": "f1.js", "isDependency": true },
  { "path": "f2.js", "isDependency": true },
  { "path": "f3.js", "isDependency": false },
  { "path": "f4.js", "isDependency": false },
  { "path": "f5.js", "isDependency": false },
  { "path": "f6.js", "isDependency": false }
];

而且我有一个加载脚本的异步函数,但是我在设置异步/等待或承诺等待前两个脚本加载,然后让其他脚本按任何顺序加载时遇到了问题。

代码语言:javascript
运行
复制
private async loadJsFileAsync(filePath: string) {
  return new Promise((resolve, reject) => {
    if (!document.getElementById(filePath)) {
      var script = document.createElement('script');

      script.onload = function () {
        // mark with attribute so we know that it's loaded
        script.attributes["data-loaded"] = "true";
        resolve();
      }
      script.onerror = function (err) {
        reject(err);
      }

      script.type = "text/javascript";
      script.src = filePath
      script.id = filePath;
      document.getElementsByTagName('head')[0].appendChild(script);

    } else {
      // file processed, but check to see it actually loaded
      var s1 = <HTMLScriptElement>document.getElementById(filePath);
      var loadedAttribute = s1.attributes["data-loaded"] === "true";
      if (loadedAttribute) {
        resolve();
      } else {

        // add event listeners (in addition to the existing ones)
        s1.addEventListener("load", function () {
          resolve();
        });
        s1.addEventListener("error", function (err) {
          reject(err);
        });
      }
    }
  });
}

目前,我使用的异步函数只有一个所需的脚本,其方式如下:

代码语言:javascript
运行
复制
this.loadJsFileAsync("f1.js").then(value => {

  // load other files
  loadJsFile("f3.js");
  loadJsFile("f4.js");
  loadJsFile("f5.js");
  loadJsFile("f6.js");
});

private loadJsFile(filePath: string) {
  var script = document.createElement('script');
  script.type = "text/javascript";
  script.src = filePath + this.version();
  script.id = filePath;
  document.getElementsByTagName('head')[0].appendChild(script);
}   
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-04-09 23:38:39

首先,为什么不使用requirejs或其他模块加载程序呢?它们为您提供了链接脚本的能力,以便首先加载依赖项。其次,我认为这就是你想要的:

这里肯定有改进和优化的空间,但是它应该会给您您想要的结果。

代码语言:javascript
运行
复制
class Script {
    constructor(path, dependencyOrder) {
        this.path = path;
        this.dependencyOrder = dependencyOrder;
    }
}
class ScriptLoader {
    constructor() {
        this.scripts = [];

    }
    addScript(script) {
        const exists = this.scripts.find( s => s.path.toLowerCase() === script.path.toLowerCase());
        if (!exists) {
            this.scripts.push(script);
        }
    }
    async loadScripts() {
        if (Array.isArray(this.scripts)) {
            const orderedScripts = this.orderScriptsByDependency();
            let scriptsLoaded = false;
            let counter = 0;
            while (!scriptsLoaded) {
                const _script = orderedScripts[counter]
                await this.loadScript(_script, _script.dependencyOrder > -1);
                counter += 1;
                scriptsLoaded = counter === orderedScripts.length;
            }
        }
    }
    async loadScript(script, waitToLoad) {
        return new Promise( (resolve, reject) => {
            const scriptTag = document.createElement('script');
            scriptTag.src = script.path;
            if (waitToLoad) {
                scriptTag.async = true;
                document.body.appendChild(scriptTag);
                scriptTag.onload = () => { resolve(); }
            } else {
                document.body.appendChild(scriptTag);
                resolve();
            }
        } );
    }
    orderScriptsByDependency() {
        if (Array.isArray(this.scripts)) {
            return this.scripts.sort( (a, b) => {
                return a.dependencyOrder - b.dependencyOrder;
            });
        }
        return null;
    }
}

使用

代码语言:javascript
运行
复制
class IndexView {
    constructor() {
        this.loader = new ScriptLoader();
        this.init();
    }
    async init() {
        this.loader.addScript(new Script('scripts/script0.js', 0));
        this.loader.addScript(new Script('scripts/script1.js', 1));
        this.loader.addScript(new Script('scripts/script2.js', 2));
        await this.loader.loadScripts();
    }
}

要求

票数 2
EN

Stack Overflow用户

发布于 2019-04-10 00:14:07

如果你想保持秩序,你可以像这样利用onload of HtmlScriptElement

代码语言:javascript
运行
复制
const loadScripts = (urls: string[]): void => {
  urls.forEach((url, index) => {
    const js = loadScript(url);
    if (index < urls.length) {
      js.onload = () => {
        loadScript(urls[index + 1]);
      };
    }
  });
};

const loadScript = (url: string): HTMLScriptElement => {
  const js = document.createElement("script");
  js.setAttribute("src", url);
  document.body.appendChild(js);
  return js;
};

就这样叫它:

代码语言:javascript
运行
复制
loadScripts(["script1.js", "script2.js", "script3.js"]);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55602445

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档