探索 JavaScript 定时器

目录

setTimeout()

当编写 JavaScript 代码时,可能希望延迟函数的执行。

这就是 setTimeout 的工作。 指定一个回调函数以供稍后执行,并指定希望它稍后运行的时间(以毫秒为单位)的值:

setTimeout(() => {
  // 2 秒之后运行
}, 2000)

setTimeout(() => {
  // 50 毫秒之后运行
}, 50)

该语法定义了一个新的函数。 可以在其中调用所需的任何其他函数,也可以传入现有的函数名称和一组参数:

const myFunction = (firstParam, secondParam) => {
  // 做些事情
}

// 2 秒之后运行
setTimeout(myFunction, 2000, firstParam, secondParam)

setTimeout 会返回定时器的 id。 通常不使用它,但是可以保存此 id,并在要删除此安排的函数执行时清除它:

const id = setTimeout(() => {
  // 应该在 2 秒之后运行
}, 2000)

// 改变主意了
clearTimeout(id)

零延迟

如果将超时延迟指定为 0,则回调函数会被尽快执行(但是是在当前函数执行之后):

setTimeout(() => {
  console.log('后者 ')
}, 0)

console.log(' 前者 ')

会打印 前者 后者

通过在调度程序中排队函数,可以避免在执行繁重的任务时阻塞 CPU,并在执行繁重的计算时执行其他函数。

某些浏览器(IE 和 Edge)实现的 setImmediate() 方法具有相同的确切功能,但是不是标准的,并且在其他浏览器上不可用。但是在 Node.js 中它是标准的函数。

setInterval()

setInterval 是一个类似于 setTimeout 的函数,不同之处在于:它会在指定的特定时间间隔(以毫秒为单位)一直地运行回调函数,而不是只运行一次:

setInterval(() => {
  // 每 2 秒运行一次
}, 2000)

上面的函数每隔 2 秒运行一次,除非使用 clearInterval 告诉它停止(传入 setInterval 返回的间隔定时器 id):

const id = setInterval(() => {
  // 每 2 秒运行一次
}, 2000)

clearInterval(id)

通常在 setInterval 回调函数中调用 clearInterval,以使其自行判断是否应该再次运行或停止。 例如,此代码会运行某些事情,除非 App.somethingIWait 具有值 arrived

const interval = setInterval(() => {
  if (App.somethingIWait === 'arrived') {
    clearInterval(interval)
    return
  }
  // 否则做些事情
}, 100)

递归的 setTimeout

setInterval 每 n 毫秒启动一个函数,而无需考虑函数何时完成执行。

如果一个函数总是花费相同的时间,那就没问题了:

setInterval 工作正常

函数可能需要不同的执行时间,这具体取决于网络条件,例如:

setInterval 不同的时长

也许一个较长时间的执行会与下一次执行重叠:

setInterval 重叠

为了避免这种情况,可以在回调函数完成时安排要被调用的递归的 setTimeout:

const myFunction = () => {
  // 做些事情

  setTimeout(myFunction, 1000)
}

setTimeout(myFunction, 1000)

实现此方案:

递归的 setTimeout

setTimeoutsetInterval 可通过定时器模块在 Node.js 中使用。

Node.js 还提供 setImmediate()(相当于使用 setTimeout(() => {}, 0)),通常用于与 Node.js 事件循环配合使用。