首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

JavaScript 非同步腳本載入器實作:防重複請求與 Promise 封裝

     編輯:PHP 綜合知識

問題情境

頁面多個獨立組件(如 A、B 兩個上傳模組)同時依賴大型第三方庫(如 plupload.js、vue.js)。若各自獨立發起請求,會造成重複下載、競態條件與資源浪費。

基礎版:單一載入器

利用 jQuery $.Deferred() 與鎖機制,確保同一腳本只發一次請求:

var loadVue = (function() {
    var lock = false;
    var promiseStack = [];
    
    return function() {
        var deferred = $.Deferred();
        if (lock) {
            promiseStack.push(deferred);
        } else {
            lock = true;
            if (window.Vue) {
                lock = false;
                deferred.resolve();
            } else {
                $.getScript('/assets/vue/vue.min.js', function() {
                    lock = false;
                    deferred.resolve();
                    promiseStack.forEach(function(p) { p.resolve(); });
                    promiseStack = [];
                });
            }
        }
        return deferred.promise();
    };
})();

// 使用方式
loadVue().then(function() { /* Vue 已就緒 */ });

進階版:通用載入器產生器

支援多種不同腳本,避免重複撰寫邏輯:

var Loader = (function() {
    var promiseStacks = {};
    
    function generate(name, globalVar, url) {
        var loader = function() {
            if (!promiseStacks[name]) promiseStacks[name] = [];
            var deferred = $.Deferred();
            
            if (loader.lock) {
                promiseStacks[name].push(deferred);
            } else {
                loader.lock = true;
                if (window[globalVar]) {
                    loader.lock = false;
                    deferred.resolve();
                } else {
                    $.getScript(url, function() {
                        loader.lock = false;
                        deferred.resolve();
                        promiseStacks[name].forEach(function(p) { p.resolve(); });
                        promiseStacks[name] = [];
                    });
                }
            }
            return deferred.promise();
        };
        return loader;
    }
    return { generate: generate };
})();

// 註冊全域載入器
window.loadVue = Loader.generate('vue', 'Vue', '/assets/vue/vue.min.js');
window.loadPlupload = Loader.generate('plupload', 'plupload', '/assets/plupload/plupload.full.min.js');

網路面板驗證

套用後,Network 面板顯示同一腳本僅請求一次,後續呼叫直接從快取或 Promise 解析取得,解決並發重複下載問題。

現代替代方案

  • ES Modules + dynamic import():原生瀏覽器支援,自動去重。
  • RequireJS / SystemJS:成熟 AMD/UMD 載入器。
  • Webpack/Vite 程式碼分割:建置期自動處理共用依賴。

但在無法使用建置工具的舊專案中,上述 Promise 型載入器仍是輕量可靠的選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved