分時函數 & 節流函數

 

分時函數 & 節流函數

1.函數節流

JavaScript 中的函數大多數狀況下都是由用戶主動調用觸發的,除非是函數自己的實現不合 理,不然咱們通常不會遇到跟性能相關的問題。但在一些少數狀況下,函數的觸發不是由用戶直 接控制的。在這些場景下,函數有可能被很是頻繁地調用,而形成大的性能問題。下面將列舉一 些這樣的場景 JavaScript 中的函數大多數狀況下都是由用戶主動調用觸發的,除非是函數自己的實現不合 理,不然咱們通常不會遇到跟性能相關的問題。但在一些少數狀況下,函數的觸發不是由用戶直 接控制的。在這些場景下,函數有可能被很是頻繁地調用,而形成大的性能問題。下面將列舉一 些這樣的場景

(1). 函數被頻繁調用的場景瀏覽器

window.onresize 事件。咱們給 window 對象綁定了 resize 事件,當瀏覽器窗口大小被拖動 而改變的時候,這個事件觸發的頻率很是之高。若是咱們在 window.onresize 事件函數裏 有一些跟 DOM節點相關的操做,而跟 DOM節點相關的操做每每是很是消耗性能的,這 時候瀏覽器可能就會吃不消而形成卡頓現象app

mousemove 事件。一樣,若是咱們給一個 div 節點綁定了拖曳事件(主要是 mousemove),當 div 節點被拖動的時候,也會頻繁地觸發該拖曳事件函數函數

上傳進度。微雲的上傳功能使用了公司提供的一個瀏覽器插件。該瀏覽器插件在真正開 始上傳文件以前,會對文件進行掃描並隨時通知 JavaScript函數,以便在頁面中顯示當前 的掃描進度。但該插件通知的頻率很是之高,大約一秒鐘 10次,很顯然咱們在頁面中不 須要如此頻繁地去提示用戶性能

(2). 函數節流原理spa

咱們整理上面提到的三個場景,發現它們面臨的共同問題是函數被觸發的頻率過高。 好比咱們在 window.onresize 事件中要打印當前的瀏覽器窗口大小,在咱們經過拖曳來改變 窗口大小的時候,打印窗口大小的工做 1秒鐘進行了 10次。而咱們實際上只須要 2次或者 3次。 這就須要咱們按時間段來忽略掉一些事件請求,好比確保在 500ms內只打印一次。很顯然,咱們 能夠藉助 setTimeout 來完成這件事情插件

var throttle = function(fn, duration) {
        var _self = fn,
            firstTime = true,
            timer;
        if (firstTime) {
            fn();
           return firstTime = false;
        }
        if(timer){
         return false
        }
        
        timer = setTimeout(() => {
            clearTimeout(timer)
            timer = null;
            fn()
            
        }, duration||500);
    };
    window.onresize = throttle(function (params) {
        console.log(1)
    }) 

 

2. 分時函數

有時候是咱們主動須要大量的頻繁調用某個函數,好比在頁面中插入1000個div。在短期內往頁面中大量添加 DOM節點顯然也會讓瀏覽器吃不消,咱們看到的結果每每就 是瀏覽器的卡頓甚至假死

(1). 解決原理code

咱們能夠把函數讓建立節點的工做分批進行,好比把 1秒鐘建立 1000個節點,改成每隔 200毫秒建立 8個節點。對象

 

 /**
     * @param {Array} ary - 必填---  要建立的集合
     * @param {Function} fn -必填---  業務邏輯代碼
     * @param {Number} count - 可選---每批建立幾個
     */
    var timeChunk = function(ary, fn, count) {
        var obj,
            timer;
        var start = function() {
            for (var i = 0; i < Math.min(count || 1, ary.length); i++) {
                obj = ary.shift()
                fn(obj)
            }

        }
        return function() {
            timer = setInterval(() => {
                if (ary.length === 0) {
                    return clearInterval(timer)
                }
                start();
            }, 500);

        }

    }
    var ary = [];

    for (var i = 1; i <= 10; i++) {
        ary.push(i);
    };

    var renderFriendList = timeChunk(ary, function(n) {
        var div = document.createElement('div');
        div.innerHTML = n;
        document.body.appendChild(div);
    }, 2);

    renderFriendList();
相關文章
相關標籤/搜索