自学内容网 自学内容网

setTimeout,setInterval ,requestAnimationFrame定时器

setTimeout,setInterval ,requestAnimationFrame定时器

定时器函数通常用于执行定时任务,也就是说你做了一个功能放在定时器函数里,它可以在特定的时间去执行你的指令,或者说隔多长时间(单位时间内—毫秒为单位)去执行。

💫在异步编程中 定时函数也是不可缺席的,常见的定时器有: setTimeoutsetIntervalrequestAnimationFrame

🏃setTimeout

多人认为 setTimeout是延时多久后才开始执行函数,其实这里存在一些误解:

1️⃣精确延时
误解:很多人认为 setTimeout 会在指定的毫秒数后精确地执行回调函数。
事实 :实际上,setTimeout 只是告诉 JavaScript 引擎在指定的时间之后尝试执行回调函数。由于 JavaScript 是单线程的,如果在这段时间内主线程上有其他任务在运行,那么回调函数的执行会被推迟到当前任务完成之后。
2️⃣ 立即执行
误解:有些人认为将延迟设置为 0 毫秒(setTimeout(callback, 0))会让回调函数立即执行。
事实 :即使延迟设置为 0 毫秒,回调函数也会被推入事件队列,并在当前执行栈清空后执行。这是因为 JavaScript 的事件循环机制决定了任何 setTimeout 调用都会进入微任务队列(非立即执行的异步任务队列),并在当前宏任务完成后被执行。
3️⃣并发执行
误解: 有时人们误以为多个 setTimeout 调用可以同时执行。
事实 : 虽然 setTimeout 可以并行设置多个定时器,但由于 JavaScript 的单线程特性,这些回调函数仍然会按顺序执行,不会同时运行。
4️⃣多次执行
误解:一些开发者可能认为 setTimeout 会多次执行,特别是当他们试图在一个循环中设置多个定时器时。
事实 : 如果不适当地设置多个定时器,可能会导致意料之外的行为。例如,在循环中设置多个定时器而不考虑它们的执行顺序,可能导致所有回调几乎同时触发。

☕️setInterval

🎪 setInterval 函数作用和 setTimeout 基本一致,,区别在于setInterval是每隔一段时间执行一次回调函数。
🚣 通常情况不是很推荐使用 setInterval,原因有两点:他和 setTime基本一致,不能保证在预期时间执行任务,其次就是存在执行积累的问题,比如说以下代码:

// 定义一个名为 demo 的函数
function demo() {
    // 使用 setInterval 设置一个定时器,每隔 1000 毫秒(1秒)执行一次提供的回调函数
    setInterval(function() {
        console.log(2); // 每次执行时打印数字 2 到控制台
    }, 1000); // 设置间隔时间为 1000 毫秒

    // 尝试调用 sleep 函数,等待 2000 毫秒(2秒)
    // 注意:JavaScript 中没有原生的 sleep 函数,这里是模拟休眠
    sleep(2000); // 这里的 sleep 函数在标准 JavaScript 中是不存在的

    // 由于 JavaScript 是单线程的,这里 sleep 函数如果是阻塞的,
    // 那么它将会阻止其他所有代码(包括定时器)的执行,直到它完成
}

// 调用 demo 函数
demo();

🚅以上代码在浏览器环境中,如果定时器出现了耗时操作,由于 JavaScript 是单线程的,这里 sleep 函数如果是阻塞的,多个回调函数会在耗时操作结束以后同时执行,这样就可能会带来性能上的问题。

🎡 requestAnimationFrame

requestAnimationFrame 是一种在浏览器中用来执行动画的技术,它可以让动画更流畅且性能更高。
🚁 相比起上面两个函数它有以下优点:

✖️ 与屏幕刷新率同步:
requestAnimationFrame 的回调会在浏览器的下一帧绘制之前被调用,通常每秒 60 帧(即每 16.67 毫秒一帧),自带节流功能,这使得动画更加平滑。
➕ 自动暂停:
当包含动画的标签页不在前台时, requestAnimationFrame 会自动暂停,从而节省计算资源。
➖ 更高效:
如果浏览器在某一帧内无法渲染(例如因为 CPU 负载过高), requestAnimationFrame 不会堆积回调,而是跳过这一帧。

🌠requestAnimationFrame 函数的延时效果是精确的,没有其他定时器时间不准的问题,当然也可以通过该函数去实现 setTimeout

// 定义一个模拟 setInterval 的函数
function setInterval(callback, interval) {
    // 用于存储 requestAnimationFrame 的返回值
    let timer;

    // 获取当前时间的函数引用,提高代码可读性和一致性
    const now = Date.now;

    // 初始化开始时间和结束时间
    let startTime = now();
    let endTime = startTime;

    // 定义一个内部循环函数
    const loop = () => {
        // 使用 requestAnimationFrame 请求下一帧
        timer = window.requestAnimationFrame(loop);

        // 获取当前时间
        endTime = now();

        // 如果从开始到现在的时间差大于或等于指定的间隔时间 interval
        if (endTime - startTime >= interval) {
            // 重置开始时间和结束时间
            startTime = endTime = now();

            // 调用回调函数,并传入当前的 timer 值
            callback(timer);
        }
    }

    // 第一次调用 loop 函数,开始循环
    timer = window.requestAnimationFrame(loop);

    // 返回 timer 值,以便将来可以通过它取消动画
    return timer;
}

// 初始化计数器
let a = 0;

// 使用自定义的 setInterval 函数,每隔 1000 毫秒(1秒)执行一次回调函数
setInterval(timer => {
    // 打印数字 1 到控制台
    console.log(1);

    // 计数器增加
    a++;

    // 如果计数器 a 达到 3,则取消动画
    if (a === 3) {
        cancelAnimationFrame(timer);
    }
}, 1000);

今天的分享就到这里啦,感谢大家的阅览,小江会一直与大家一起努力,文章中如有不足之处,你的支持是我前进的最大动力,请多多指教,感谢支持,持续更新中 ……


原文地址:https://blog.csdn.net/weixin_53752776/article/details/142718071

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!