使用requestAnimationFrame模拟实现setTimeout和setInterval

简介: `rafTimeout` 函数采用 `requestAnimationFrame` 实现延时或周期性调用,提供与 `setTimeout` 和 `setInterval` 类似的功能。接受参数包括要执行的函数 `fn`、延迟时间 `delay`(默认 0ms)及是否周期执行 `interval`(默认为单次执行)。返回值为包含 `id` 的对象,可用于取消定时器。通过 `cancelRaf` 或 `cancelAnimationFrame` 方法可取消对应的 `rafTimeout` 定时器。

rafTimeout 函数与 setTimeout 和 setInterval 用法基本一致!

接受参数:

  • fn:延迟 delay ms 后要执行的函数

  • delay(可选):延迟的毫秒数,默认 0ms

  • interval(可选):默认情况下 rafTimeout 等效于 setTimeout 功能,如果要使用 setInterval 功能,则需传入第三个参数(interval: true)

返回值(用于取消 rafTimeout):

  • raf: { id: number }

取消 rafTimeout 定时器:

  • cancelRaf(raf)

  • cancelAnimationFrame(raf.id)

/**
 * 使用requestAnimationFrame实现的延迟setTimeout或间隔setInterval调用函数。
 *
 * @param fn 要执行的函数。
 * @param delay 延迟的时间,单位为ms,默认为0,表示不延迟立即执行。
 * @param interval 是否间隔执行,如果为true,则在首次执行后,以delay为间隔持续执行。
 * @returns 返回一个对象,包含一个id属性,该id为requestAnimationFrame的调用ID,可用于取消动画帧。
 */
export function rafTimeout(fn: Function, delay = 0, interval = false): object {
  let start: number | null = null // 记录动画开始的时间戳
  function timeElapse(timestamp: number) {
    // 定义动画帧回调函数
    /*
      timestamp参数:与performance.now()的返回值相同,它表示requestAnimationFrame()开始去执行回调函数的时刻
    */
    if (!start) {
      // 如果还没有开始时间,则以当前时间为开始时间
      start = timestamp
    }
    const elapsed = timestamp - start
    if (elapsed >= delay) {
      try {
        fn() // 执行目标函数
      } catch (error) {
        console.error('Error executing rafTimeout function:', error)
      }
      if (interval) {
        // 如果需要间隔执行,则重置开始时间并继续安排下一次动画帧
        start = timestamp
        raf.id = requestAnimationFrame(timeElapse)
      }
    } else {
      raf.id = requestAnimationFrame(timeElapse)
    }
  }
  interface AnimationFrameID {
    id: number
  }
  // 创建一个对象用于存储动画帧的ID,并初始化动画帧
  const raf: AnimationFrameID = {
    id: requestAnimationFrame(timeElapse)
  }
  return raf
}
/**
 * 用于取消 rafTimeout 函数
 *
 * @param raf - 包含请求动画帧ID的对象。该ID是由requestAnimationFrame返回的。
 *              该函数旨在取消之前通过requestAnimationFrame请求的动画帧。
 *              如果传入的raf对象或其id无效,则会打印警告。
 */
export function cancelRaf(raf: { id: number }): void {
  if (raf && raf.id && typeof raf.id === 'number') {
    cancelAnimationFrame(raf.id)
  } else {
    console.warn('cancelRaf received an invalid id:', raf)
  }
}
相关文章
|
前端开发
setInterval
setInterval
42 0
|
消息中间件 JavaScript 前端开发
setTimeout和setInterval
setTimeout和setInterval
|
JavaScript 前端开发
js 定时器用法详解——setTimeout()、setInterval()、clearTimeout()、clearInterval()
写在前面: 在js应用中,定时器的作用就是可以设定当到达一个时间来执行一个函数,或者每隔几秒重复执行某段函数。这里面涉及到了三个函数方法:setInterval()、setTimeout()、clearInterval(),本文将围绕这三种函数的用法,来实现定时器的功能,需要的朋友可以过来参考下,喜欢的可以点波赞,或者关注一下本人,希望对大家有所帮助。 定时器的应用需求: 1.设定一个时间,当时间到达的时候执行函数————比如:倒计时跳转页面等等。 2.每隔一段时间重复执行某段函数————比如抢票软件,比如设定500毫秒就重复刷新一次页面等等。 倒计时跳转实现demo:
638 0
js 定时器用法详解——setTimeout()、setInterval()、clearTimeout()、clearInterval()
相比 setInterval(),更推荐 setTimeout()
相比 setInterval(),更推荐 setTimeout()
92 0
手写系列 # 2:利用 requestAnimationFrame 实现 setInterval 计时器
手写系列 # 2:利用 requestAnimationFrame 实现 setInterval 计时器
316 0
手写系列 # 2:利用 requestAnimationFrame 实现 setInterval 计时器
15、计时器方法1(setInterval、clearInterval)
15、计时器方法1(setInterval、clearInterval)
147 0
|
JavaScript 前端开发 Java
|
JavaScript 前端开发