Vue源碼思想在工做中的應用

1、背景

因爲電腦CPU、內存等的限制,可以同時啓動的任務數有必定限制,例如一臺電腦可以執行5個異步任務,可是目前有100個異步任務要執行,那麼如何讓這100個任務無間隔的快速執行完畢呢?

2、問題解答

剛遇到這個問題的時候,也是出於懵逼狀態,怎麼處理呢???碰巧的是近期學習了一些Vue的源碼知識,那麼是否是能夠借鑑其思想來解決遇到的這個難題呢?通過一步步分析,肯定答案是確定的。下面從解題思路、知識點及代碼實現來聊一聊實現過程。

2.1 解題思路

image.png

上述是整個流程圖,其流程可簡化爲如下幾個步驟:
  1. 將全部任務分爲兩組,任務組1指的是電腦能夠並行執行的異步任務,任務組2指的是其他的異步任務;
  2. 將任務組1變爲可幀聽狀態,即其發生變化時咱們可以知道;
  3. 將任務組1中的任務觸發(不觸發任務不會執行);
  4. 某一任務執行完畢後,將任務組2中的一個任務填充到可幀聽狀態的任務組1中;
  5. 任務按照固定數量不斷執行,直到全部任務執行完畢。前端

    2.2 知識點

    在Vue源碼中,Vue2.x使用Object.defineProperty()實現對數據的幀聽;Vue3.0使用Proxy實現對數據的幀聽。本着趕時髦和Proxy確實優秀的態度,在實現過程當中也應用了Proxy。Proxy做爲一個新的知識點,先了解一下其定義及使用方法。

    2.2.1 定義

    Proxy中文意思是「代理」,是在目標對象之間架設一層「攔截」,從而能夠修改某些操做的默認行爲。Proxy共支持十三種攔截操做:get、set、has、deleteProperty、ownKeys、getOwnPropertyDescriptor、defineProperty、preventExtensions、getPrototypeOf、isExtensible、setPrototypeOf、apply、construct。

    2.2.2 簡單使用

    function testProxy(obj) {
     return new Proxy(obj, {
         get: (target, key) => {
             console.log(`我被get攔截器攔截了,攔截的屬性是${key}`);
         },
         set: (target, key, value) => {
             console.log(`我被set攔截器攔截了,攔截的屬性是${key}, 新值是${value}`);
             target[key] = value;
         }
     });
    }
    
    const testObj = {
     a: 10
    };
    const proxy = testProxy(testObj);
    
    proxy.a = 100;

    2.2.3 詳細使用

    詳細用法能夠參考阮一峯大佬的「ECMAScript 6入門」。

    2.3 代碼實現

    2.3.1 定義兩個任務隊列

    首先定義兩個任務隊列,task1爲開始執行的一批任務,task2中爲後續添加進去的任務。
    const task1 = [1, 2, 3];
    const task2 = [4, 5, 6, 7, 8];

    2.3.2 數據變爲可幀聽的函數

    利用Proxy將數據變爲可幀聽狀態
    /**
     * 監聽模塊,監聽對應數組的變化,保證其始終有必定長度的內容在運行
     *
     * @param {Array} initArr 定長任務的數組
     * @param {Function} callback 對應的回調函數
     */
    function watcher(initArr, callback) {
     const proxy = new Proxy(initArr, {
         set(target, key, value, receiver) {
             target[key] = value;
             callback(value, key, receiver);
         }
     });
     return proxy;
    }

    2.3.3 異步任務邏輯

    /**
     * 異步任務的運行邏輯
     *
     * @param {number} taskIndex 異步任務的序號
     * @param {number} index 當前任務在定長任務的序號
     * @param {Proxy} proxy Proxy實例
     */
    function asyncTask(taskIndex, index, proxy) {
     console.log(`${index}索引處的任務${taskIndex}開始執行`);
     return new Promise(resolve => {
         setTimeout(() => {
             console.log(`${index}索引處的任務${taskIndex}執行完畢`);
             // 當任務隊列2中還有任務時,進入隊列替換任務1中執行完的任務
             if (task2.length > 0) {
                 proxy[index] = task2.shift();
             }
         }, 1000 + 2000 * Math.random());
     });
    }

    2.3.4 主函數

    const proxy = watcher(task1, asyncTask);
     task1.forEach((taskIndex, index) => asyncTask(taskIndex, index, proxy));
    }
    2.3.5 執行結果
    經過結果能夠看到,當一個任務完成時馬上將有一個新的任務進入。
    0索引處的任務1開始執行
    1索引處的任務2開始執行
    2索引處的任務3開始執行
    0索引處的任務1執行完畢
    0索引處的任務4開始執行
    2索引處的任務3執行完畢
    2索引處的任務5開始執行
    1索引處的任務2執行完畢
    1索引處的任務6開始執行
    0索引處的任務4執行完畢
    0索引處的任務7開始執行
    2索引處的任務5執行完畢
    2索引處的任務8開始執行
    1索引處的任務6執行完畢
    0索引處的任務7執行完畢
    2索引處的任務8執行完畢

    3、討論

    針對此類問題的處理方式,各位大佬有新的思路與方法歡迎留言,咱們一塊兒討論,共同進步。

1.若是以爲這篇文章還不錯,來個分享、點贊吧,讓更多的人也看到數組

2.關注公衆號執鳶者,領取學習資料(前端「多兵種」資料),按期爲你推送原創深度好文app

相關文章
相關標籤/搜索