美文网首页
js去抖与节流

js去抖与节流

作者: weiee | 来源:发表于2018-08-14 22:05 被阅读0次

    在vue监听器章节用到一个js插件lodash的函数去抖(debounce)和节流(throttle)功能,之前大概知道是防止重复调用的方法。

    问题:事件频繁被触发而导致重复调用事件处理程序。

    去抖:触发某个事件规定n秒后执行事件处理程序,如果在这n秒内相同的事件被重复触发,则重新计算事件处理程序的执行时间点,即将多次触发合并为1次触发。debounce首次js实现:http://unscriptable.com/2009/03/20/debouncing-javascript-methods/.

    节流:如果事件一直被触发,而我们实际上需要定时的执行事件处理程序,则去抖方式就不再合适,因为去抖只能保证执行连续触发事件的最后一次调用。节流即:保证事件处理程序在大于等于预定周期时必定被执行1次,即以固定周期执行函数,从而降低执行次数。

    高级定时器

    js是单线程,定时器执行时间不能保证。浏览器对某个时间点代码执行优先级进行排序。js除了主执行进程外,还有一个在进程空闲时执行的任务队列。在js中,没有代码是立即执行的,需要等到进程空闲时执行。

    问题:为什么说js是单线程,而又有个任务队列的概念?

    function debounce(fn, delay) {
        var timer = null;
        return function () {
            var _this = this;
            var _args = arguments;
            // 清除上一个timer
            clearTimeout(timer);
            // 当最后回调时,经过delay毫秒后执行事件处理程序
            timer = setTimeout(function() {
                fn.apply(_this, _args);
            }, delay);
        }
    }
    
    function throttle(fn, delay) {
        var last = 0;
        return function() {
            var cur = +new Date();
            if (cur - last > delay) {
                fn.apply();
                last = cur;
            }
        }
    }
    

    高级定时器
    js是单线程,定时器执行时间不能保证。浏览器对某个时间点代码执行优先级进行排序。js除了主执行进程外,还有一个需要在进程空闲时执行的任务队列。在js中,没有代码是立即执行的,需要等到进程空闲时执行。
    问题:为什么说js是单线程,而又有个任务队列的概念?
    浏览器多进程架构:chrome每个tab页单独起一个进程,防止1个tab网页崩溃影响其他被打开的网页应用。相对于线程,进程之间不共享资源和地址空间。
    浏览器内核:也称渲染引擎,处理获取的内容、整理信息(css)、计算并组合输出可视化的图像结果。
    浏览器内核多线程:
    GUI渲染线程(与JS引擎线程互斥,防止同时操作DOM)
    JS引擎线程(与GUI渲染线程互斥)
    定时触发线程
    事件触发线程
    异步HTTP请求线程

    定时器工作原理是在指定时间后将定时任务代码插入到任务队列中,注意该代码不会立即执行,除非当前队列没有其他任务。js执行过程中如果遇到定时器,会交给浏览器的其他模块处理计时(例如:webkit的webcore模块),当到达指定延时后,回调函数被放入任务队列。

    js事件循环机制,js主线程(main thread)、调用栈(call stack)、任务队列(task queue):
    micro-task: process.nextTick, Promise, Object.observe, MutationObserver
    macro-task: script整体,setTimeout, setInterval, setImmediate, I/O, UI rendering
    执行顺序:调用栈 > micro-task > macro-task
    例子:

    (function test() {
        setTimeout(function() {console.log(4)}, 0);
        new Promise(function executor(resolve) {
            console.log(1);
            for( var i=0 ; i<10000 ; i++ ) {
                i == 9999 && resolve();
            }
            console.log(2);
        }).then(function() {
            console.log(5);
        });
        console.log(3);
    })()
    

    以上输出结果为:1 2 3 5 4

    相关文章

      网友评论

          本文标题:js去抖与节流

          本文链接:https://www.haomeiwen.com/subject/yvubbftx.html