• setTimeout和setInterval


    setTimeout和setInterval都是异步任务,会进入异步任务队列。

    等待所有的同步任务执行完成后,才有可能执行。

    1.setTimeout

    1)第一个参数

    // 第一个参数不仅可以是function, 还可以是一段可执行代码的字符串格式
    setTimeout('console.log(1)', 1000); // 一秒后打印1
    // 如果上面的代码没有字符串包含,则会立即打印,定时器不起效果
    setTimeout(function timer() {
      console.log(1);
    },1000); // 效果和上面的字符串功能相同

    2) 第二个参数

    setTimeout(fn) 等同于 setTimeout(fn, 0);
    // 第二个参数没有的时候默认是0,但其实是等于4ms
    // 如果第二个参数存在,那么表示是延迟的毫秒数

    3)第三个及之后的参数

    setTimeout(function timer(a,b) {
      console.log(a,b); // 1,2
    }, 1000, 1,2); 
    // 当有第三个及之后的参数时,作为回调函数的参数传入

    4) 返回值和clearTimeout

    // 返回一个整数数字,表示定时器编号,数字依次加1
    const a = setTimeout(fn, 1000); // a =4
    const b = setTimeout(fn, 1000); // b = 5
    const c = setTimeout(fn, 1000); // c = 6
    // 将定时器编号传入clearTimeout(NO.),清除定时器

    5) 关于this

    // this可以理解成调用该函数的对象
    // 1) 直接写入回调函数
    setTimeout(function timer() {
       console.log(this); // window, 也可说明timer有个涵盖全局作用域的闭包
    })
    // 2)回调函数是对象的方法
    var obj = {
        x: 1,
        y: function() {
            console.log(this.x);
        }
    }
    setTimeout(obj.y,1000) // undefined  等同于1)中的写法
    setTimeout(obj.y(), 1000) // 立即打印1
    setTimeout('obj.y()', 1000); // 1 “字符串代码”等同于下面的写法
    setTimeout(function() {
        obj.y(); // 1
    }, 1000);

     6)应用

    • 防抖动
    // 1. 防抖动
    //例如: 当在网页中输入文本时,需要监听keydown事件去调用一个请求。但是不想在频繁触发事件的时候,频繁调用回调函数。
    // 解决办法是设置一个阈值,如果两次触发频率在阈值内,不调用;两次触发间隔超过阈值,
    function ajaxRequest() {
        console.log(this);
    }
    
    const MINTIME = 2500;
    $('#id").on('keydown', debounce(ajaxRequest, MINTIME)); 
    // 监听事件回调函数,必须是个函数;则debounce的返回值应该是个函数
    // (防抖)
    function debounce(fn, delay) {
        let timer = null;
        return function () {
            const context = this; // 作用对象,DOM
            if (timer) clearTimeout(timer);
            const args = [...arguments];
            timer = setTimeout(function() {
                fn.apply(context, args);
            }, delay);        
        }    
    }
    • 改变代码的执行顺序; 推迟代码到同步代码执行完后立即执行setTimeout(fn, 0)
    setTimeout(function () {
      console.log(1);
    }, 0);
    console.log(2);
    // 2
    // 1
    • 使用户自定义的回调函数在浏览器默认动作之后执行
    // 示例: 用户想要将实时输入的字符转为大些
    document.body.onkeypress = function() {
        // 无效;因为自定义的回调函数,通常在浏览器默认动作(keypress)之前触发;
        // 取不到this.value
        this.value = this.value.toUpperCase();
    }
    /***优化后 */
    document.body.onkeypress = function() {
        // 无效;因为自定义的回调函数,通常在浏览器默认动作(keypress)之前触发;
        // 取不到this.value
        const _this = this;
        setTimeout(function() {
            // ⚠️this的值
            _this.value = _this.value.toUpperCase();
        },0)
    }

    总结:setTimeout(fn, 0)相当于在浏览器最早获得的空闲时间段执行。

             所以那些计算量大,耗时长的任务可以分段放到setTimeout(fn, 0)中行;

             避免造成DOM阻塞等。如代码高亮处理。

    2. setInterval

    1).参数之类的同setTimeout

    2).应用

    // 1)网页动画
    // 如页面跳转后滑动到具体的位置,在位置处设置背景渐变或者字体颜色渐变来标识位置
    const timer = setInterval(function time2() {
        const div = document.getElementsByClassName("highlight")[0];
        console.log(div.style.backgroundColor)
        div.style.backgroundColor = div.style.backgroundColor === 'rgb(255, 255, 255)' ? 'rgb(0,0,0)' : 'rgb(255, 255, 255)';
    }, 500) 
    setTimeout(function time1() {
       clearInterval(timer);
    }, 3000);
    // 2) 轮询

     3. 两者的运行机制

    setTimeout(fn, delay) 和 setInterval(fn, delay) 的回调函数,都要在本轮的所有同步任务执行完才能执行。

    同步任务的执行时间不一定,可能大于delay的时间。所以回调函数是在>=delay的时间后开始执行。

    setTimeout(someTask, 100);
    veryLongTask(5000ms);
    // someTask会在5s后执行
  • 相关阅读:
    java反编译工具
    Eclipse反编译插件: Jodeclipse与JadClipse
    Apk修改利器:ApkToolkit v2.1
    新浪微博2.5.1 for Android 去广告
    java
    第K顺序统计量
    身份证号码
    pop3
    google
    Exception
  • 原文地址:https://www.cnblogs.com/lyraLee/p/11438931.html
Copyright © 2020-2023  润新知