跳至内容

古法动态按需加载JavaScript(兼容非模块脚本)

Karson Zhong · Posted on 2022-11-19 · 5 Views

关于本文

  • 介绍非模块脚本(传统脚本)使用JavaScript动态载入的方法

概要

目前有许多动态按需载入JavaScript模块的方法,比如import和require,但许多老旧的JavaScript脚本由于涉及到全局变量的操作,不支持以模块的形式载入(会出现各种错误),如果需要在代码中动态载入某些老旧的非模块脚本,这个脚本可以助你一臂之力。

脚本特点

优点

  • 简短
  • 不需要安装第三方库
  • 兼容现阶段所有浏览器(除IE)
  • 异步加载
  • 支持多个备用链接(用途:CDN炸了可以回退到本地)

缺点

  • 不具备依赖项加载功能
  • 不检测加载的内容到底是不是JavaScript(错误的内容返回200也会被当做JavaScript)

脚本

主要是动态组织script元素,其中使用Promise对加载结果进行跟踪。

/**
 * dynamically load javascript.
 * fallback if former one fails.
 * promise supported.
 * @param {*} urls source array in priority
 * @param {boolean} async
 * @param {string} type 
 * @returns Promise object
 */
function jsLoader(urls, async = true, type = "text/javascript") {
    var load = (url) => {
        return () => new Promise((resolve, reject) => {
            const scriptEle = document.createElement("script");
            try {
                scriptEle.type = type;
                scriptEle.async = async;
                scriptEle.src = url;

                scriptEle.addEventListener("load", () => resolve());
                scriptEle.addEventListener("error", () => { console.log("fallback to next src..."); rejectHandler(); });

                document.body.appendChild(scriptEle);
            } catch (error) {
                rejectHandler(error);
            }

            var rejectHandler = (e) => {
                document.body.removeChild(scriptEle);
                reject(e);
            }
        });
    };

    return urls.reduce((p, url) => p.catch(load(url)), Promise.reject()).catch((e) => { console.log("oops, all src failed"); throw e; });
}

用法

示意

  • 传入存放备选src的数组(这里选的第1,2,4个链接都是无效的)
  • 可使用Promise语法对脚本进行控制
urls = ["https://wrong.page", "2", "https://cdn.jsdelivr.net/npm/[email protected]/dist/activate-pow1er-mode.min.js", "4"]
jsLoader(urls)
    .then(() => console.log("module loaded")) //加载成功
    .catch(() => { }); //出错

输出

  • 成功载入后,后面的链接不会再继续载入
  • 失败时会有log输出,不需要的可以注释掉
GET https://wrong.page/ net::ERR_CONNECTION_CLOSED
fallback to next src...
GET file:///H:/test/2 net::ERR_FILE_NOT_FOUND
fallback to next src...
module loaded

参考

程序员,热衷于游戏开发和软件制作。但也是一个杂食动物,喜欢探索各种赛博相关的奇技淫巧。

0 0 投票数
文章评分
订阅评论
提醒
guest

0 评论
内联反馈
查看所有评论

Nova - rebirth of a wonderful theme.

Theme Nova by KarsonJo

  • Serif
  • Sans Serif
切换主题 | SCHEME TOOL
Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
0
希望看到您的想法,请您发表评论x
0
希望看到您的想法,请您发表评论x