分时函数 & 节流函数

 

分时函数 & 节流函数

1.函数节流

JavaScript 中的函数大多数情况下都是由用户主动调用触发的,除非是函数本身的实现不合 理,否则我们一般不会遇到跟性能相关的问题。但在一些少数情况下,函数的触发不是由用户直 接控制的。在这些场景下,函数有可能被非常频繁地调用,而造成大的性能问题。下面将列举一 些这样的场景

(1). 函数被频繁调用的场景

window.onresize 事件。我们给 window 对象绑定了 resize 事件,当浏览器窗口大小被拖动 而改变的时候,这个事件触发的频率非常之高。如果我们在 window.onresize 事件函数里 有一些跟 DOM节点相关的操作,而跟 DOM节点相关的操作往往是非常消耗性能的,这 时候浏览器可能就会吃不消而造成卡顿现象

mousemove 事件。同样,如果我们给一个 div 节点绑定了拖曳事件(主要是 mousemove),当 div 节点被拖动的时候,也会频繁地触发该拖曳事件函数

上传进度。微云的上传功能使用了公司提供的一个浏览器插件。该浏览器插件在真正开 始上传文件之前,会对文件进行扫描并随时通知 JavaScript函数,以便在页面中显示当前 的扫描进度。但该插件通知的频率非常之高,大约一秒钟 10次,很显然我们在页面中不 需要如此频繁地去提示用户

(2). 函数节流原理

我们整理上面提到的三个场景,发现它们面临的共同问题是函数被触发的频率太高。 比如我们在 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). 解决原理

我们可以把函数让创建节点的工作分批进行,比如把 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();

原文地址:https://www.cnblogs.com/Paul-Yellow/p/10411500.html