JavaScript設計模式之代理模式-惰性載入大檔案

2020-09-25 11:01:07

在看此文之前,建議先看前篇JavaScript設計模式之代理模式-實現載入圖片loading

1.需求

假設有一個非常大的js檔案,我們只在需要用的時候,才觸發去載入它。比如有一個應用於行動端列印紀錄檔的控制檯,在按F2才載入該檔案並列印相關紀錄檔。效果如下:

2.實現

  • 首先我們建立index.html檔案,html程式碼如下:

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>虛擬代理惰性載入檔案</title>
        <style>
            #consoleContent{
                border:1px solid #ccc;
                width: 200px;
                height: 300px;
                color:#333;
                overflow: auto;
                display: none;
            }
            #consoleContent p{
                margin: 0;
                padding: 5px 10px;
                vertical-align: middle;
                border-bottom:1px solid #ccc;
                overflow-wrap: break-word;
            }
        </style>
    </head>
    
    <body>
        <section id="consoleContent"></section>
    </body>
    
    </html>
  • 接著在以上檔案中插入script指令碼,程式碼如下:

    let miniConsole = (function () {
            let cache = [];
            // 當使用者按下F2時,開始載入真正的miniConsole.js 
            const handler = function (ev) {
                if (ev.keyCode === 113) {
                    const script = document.createElement('script');
                    script.onload = function () {
                        for (let i = 0, fn; fn = cache[i++];) {
                            fn();
                        }
                        cache = null;
                    };
                    script.type = 'text/javascript';
                    script.src = "miniConsole.js";
                    document.getElementsByTagName('head')[0].appendChild(script);
                    document.removeEventListener('keydown', handler);
                }
            };
            document.addEventListener('keydown', handler, false);
            return {
                log: function () {
                    const args = arguments;
                    cache.push(function () {
                        // 不直接用miniConsole.log(args)是為了解決傳多個引數的問題
                        return miniConsole.log.apply(miniConsole,args);
                    })
                }
            }
        })();
        miniConsole.log(11,22);
        miniConsole.log(22);
        miniConsole.log(33);

由於我們要載入的js檔案中的物件為miniConsole,所以建立了一個同名代理物件:

  1. 在其中新增監聽按鍵事件,當使用者按下F2時,才開始載入真正的miniConsole.js檔案;
  2. 實現與本體對應的log方法,檔案未載入時,先存放於快取物件cache中;
  3. 在真正的miniConsole.js載入完成後,呼叫cache中快取的方法,實現真正的列印功能。
  • 最後,miniConsole.js主要程式碼大致如下:

    miniConsole = {
        log: function () {
            const p = document.createElement('p');
            p.innerHTML = Array.prototype.join.call(arguments);
            const content = document.getElementById('consoleContent');
            content.appendChild(p);
            content.style.display = 'block';
        }
    };

3.思路總結

以上miniConsole.js有時候需要處理各種型別的紀錄檔列印,導致檔案會更大。但我們這個功能不一定使用者都會用,所以實現惰性載入,減少網路開銷。

當我們遇到大檔案且非必要的功能,我們可以用虛擬代理實現惰性載入,步驟如下:

  1. 建立與原檔案介面相同的同名代理物件;
  2. 在特定需要的情況(如監聽按鍵)時載入原檔案;
  3. 在代理物件介面中快取所有的呼叫,並監聽檔案載入,等檔案載入完成時再進行執行。

代理模式系列:

實現載入圖片loading

頻繁傳送請求效能優化

注:參考書籍《JavaScript設計模式與開發實踐》,喜歡可以關注博主哦,不斷更新設計模式系列學習筆記~

不要吝嗇點贊評論哦~