You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免依赖shared_library.js的JS组件重复注入deferred脚本?

解决共享库重复注入的问题

要避免shared_library.js被重复注入,核心是跟踪脚本的加载状态,而不是仅检查最终生成的window.MyLibrary(因为加载过程中这个对象还未存在)。以下是几种实用方案:

方案1:全局状态标记跟踪加载流程

在全局作用域设置一个标记,记录共享库的三种状态:未加载、加载中、已加载。每个组件先检查这个标记,再决定后续操作:

// first_widget.js 和 second_widget.js 共用的逻辑
var loadCallback = function () {
    // 使用 window.MyLibrary
};

(function(document) {
    // 全局标记:跟踪共享库的加载状态
    window._MyLibraryStatus = window._MyLibraryStatus || 'unloaded';

    if (window._MyLibraryStatus === 'loaded') {
        // 库已加载完成,直接执行回调
        loadCallback();
        return;
    }

    if (window._MyLibraryStatus === 'loading') {
        // 库正在加载中,等待加载完成后执行回调
        var checkInterval = setInterval(function() {
            if (window._MyLibraryStatus === 'loaded') {
                clearInterval(checkInterval);
                loadCallback();
            }
        }, 50);
        return;
    }

    // 开始加载共享库
    window._MyLibraryStatus = 'loading';
    var script = document.createElement('script');
    var firstScript = document.getElementsByTagName('script')[0];
    
    script.src = 'https://example.com/shared_library.js';
    script.defer = true;
    
    script.onload = function () {
        window._MyLibraryStatus = 'loaded';
        loadCallback();
    };
    
    // 处理加载失败的情况(可选)
    script.onerror = function () {
        window._MyLibraryStatus = 'unloaded';
        console.error('Failed to load shared_library.js');
    };

    firstScript.parentNode.insertBefore(script, firstScript);
}(document));

方案2:检查DOM中已存在的脚本标签

直接查找DOM中是否已经存在指向shared_library.js的script标签,避免重复创建:

// first_widget.js 和 second_widget.js 共用的逻辑
var loadCallback = function () {
    // 使用 window.MyLibrary
};

(function(document) {
    // 检查是否已经注入过该脚本
    var existingScript = document.querySelector('script[src="https://example.com/shared_library.js"]');
    
    if (existingScript) {
        // 脚本已存在,判断是否加载完成
        if (window.MyLibrary) {
            loadCallback();
        } else {
            // 脚本正在加载,监听其onload事件
            existingScript.addEventListener('load', loadCallback);
        }
        return;
    }

    // 首次注入脚本
    var script = document.createElement('script');
    var firstScript = document.getElementsByTagName('script')[0];
    
    script.src = 'https://example.com/shared_library.js';
    script.defer = true;
    script.onload = loadCallback;

    firstScript.parentNode.insertBefore(script, firstScript);
}(document));

方案3:用Promise统一管理加载状态(现代浏览器适用)

利用Promise的特性,将共享库的加载过程封装为一个全局Promise,多个组件可以共享这个Promise的状态:

// first_widget.js 和 second_widget.js 共用的逻辑
var loadCallback = function () {
    // 使用 window.MyLibrary
};

(function(document) {
    // 全局Promise:共享库加载完成的Promise
    window._MyLibraryPromise = window._MyLibraryPromise || new Promise(function(resolve, reject) {
        var script = document.createElement('script');
        var firstScript = document.getElementsByTagName('script')[0];
        
        script.src = 'https://example.com/shared_library.js';
        script.defer = true;
        
        script.onload = function () {
            resolve(window.MyLibrary);
        };
        
        script.onerror = function () {
            reject(new Error('Failed to load shared_library.js'));
        };

        firstScript.parentNode.insertBefore(script, firstScript);
    });

    // 等待Promise完成后执行回调
    window._MyLibraryPromise.then(loadCallback).catch(function(err) {
        console.error(err);
    });
}(document));

以上三种方案都能有效避免重复注入shared_library.js,其中方案3更符合现代JS的异步编程习惯,方案1和2兼容性更好,可根据实际场景选择。

内容的提问来源于stack exchange,提问作者gremo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 16:36:42