Node.js Timers 模块

Java FileNode.js 内置模块


Node.js 的 timers 模块提供了一系列函数,用于在特定时间后执行代码或在指定时间间隔重复执行代码。这些功能对于实现延迟执行、周期性任务和超时控制非常有用。

虽然 timers 模块是 Node.js 的核心模块,但它的方法如 setTimeout(), setInterval()setImmediate() 是全局可用的,无需显式导入。


主要定时器函数

setTimeout()

setTimeout() 函数用于在指定的毫秒数后执行一次回调函数。

实例

// 2秒后打印消息
setTimeout(() => {
  console.log('这条消息将在2秒后显示');
}, 2000);

参数说明

  1. 回调函数:要执行的函数
  2. 延迟时间:以毫秒为单位的时间(1000毫秒=1秒)
  3. 可选参数:传递给回调函数的额外参数

实例

// 带额外参数的示例
setTimeout((name, age) => {
  console.log(`你好,${name},你今年${age}岁`);
}, 1000, '张三', 25);

clearTimeout()

clearTimeout() 用于取消之前通过 setTimeout() 设置的定时器。

实例

const timerId = setTimeout(() => {
  console.log('这条消息不会显示');
}, 2000);

clearTimeout(timerId); // 取消定时器

setInterval()

setInterval() 函数用于每隔指定的毫秒数重复执行回调函数。

实例

// 每隔1秒打印一次消息
let counter = 0;
const intervalId = setInterval(() => {
  counter++;
  console.log(`这是第 ${counter} 次执行`);
  if (counter === 5) {
    clearInterval(intervalId); // 停止定时器
  }
}, 1000);

clearInterval()

clearInterval() 用于停止之前通过 setInterval() 设置的重复定时器。

实例

const intervalId = setInterval(() => {
  console.log('这条消息会重复显示');
}, 1000);

// 5秒后停止定时器
setTimeout(() => {
  clearInterval(intervalId);
}, 5000);

setImmediate()

setImmediate() 函数用于在当前事件循环结束时执行回调函数。

实例

console.log('开始');

setImmediate(() => {
  console.log('立即执行回调');
});

console.log('结束');

// 输出顺序:
// 开始
// 结束
// 立即执行回调

clearImmediate()

clearImmediate() 用于取消之前通过 setImmediate() 设置的立即执行回调。

实例

const immediateId = setImmediate(() => {
  console.log('这条消息不会显示');
});

clearImmediate(immediateId);

定时器的执行顺序

理解 Node.js 事件循环对于掌握定时器的执行顺序非常重要。以下是几种定时器的执行顺序:

  1. 同步代码:最先执行
  2. process.nextTick():在当前阶段结束后立即执行
  3. Promise 回调:微任务队列
  4. setImmediate():在 I/O 回调之后执行
  5. setTimeout() 和 setInterval():在检查阶段执行

实例

console.log('开始');

setTimeout(() => console.log('setTimeout'), 0);
setImmediate(() => console.log('setImmediate'));
process.nextTick(() => console.log('nextTick'));
Promise.resolve().then(() => console.log('Promise'));

console.log('结束');

// 典型输出顺序:
// 开始
// 结束
// nextTick
// Promise
// setTimeout
// setImmediate

高级用法与注意事项

定时器的取消

所有定时器函数都会返回一个 Timeout 对象,可以用于取消定时器。即使定时器已经执行,调用取消函数也是安全的。

实例

const timeout = setTimeout(() => {}, 1000);
clearTimeout(timeout); // 安全调用,即使定时器已执行

定时器的精度

Node.js 的定时器不能保证精确的执行时间,它们表示的是"至少"等待的时间。系统负载和其他因素可能会影响实际执行时间。

内存泄漏

忘记清除 setInterval() 定时器是常见的内存泄漏来源。确保在不需要时清除定时器。

实例

// 错误的做法 - 可能导致内存泄漏
setInterval(() => {
  // 执行某些操作
}, 1000);

// 正确的做法 - 在适当的时候清除定时器
const interval = setInterval(() => {
  // 执行某些操作
  if (someCondition) {
    clearInterval(interval);
  }
}, 1000);

递归 setTimeout 替代 setInterval

对于需要固定间隔但每次执行时间不确定的任务,使用递归 setTimeoutsetInterval 更可靠。

实例

function doSomething() {
  console.log('执行任务...');
 
  // 模拟任务执行时间不确定
  const delay = Math.random() * 1000;
 
  setTimeout(doSomething, 1000 + delay);
}

setTimeout(doSomething, 1000);

实际应用示例

实现简单的倒计时

实例

function countdown(seconds) {
  let current = seconds;
 
  console.log(`倒计时开始:${current}秒`);
 
  const timer = setInterval(() => {
    current--;
   
    if (current <= 0) {
      clearInterval(timer);
      console.log('倒计时结束!');
    } else {
      console.log(`剩余时间:${current}秒`);
    }
  }, 1000);
}

countdown(5);

请求超时处理

实例

function fetchWithTimeout(url, timeout = 5000) {
  return new Promise((resolve, reject) => {
    const timeoutId = setTimeout(() => {
      reject(new Error(`请求超时(${timeout}ms)`));
    }, timeout);
   
    fetch(url)
      .then(response => {
        clearTimeout(timeoutId);
        resolve(response);
      })
      .catch(error => {
        clearTimeout(timeoutId);
        reject(error);
      });
  });
}

// 使用示例
fetchWithTimeout('https://api.example.com/data')
  .then(data => console.log(data))
  .catch(error => console.error(error));

通过掌握 Node.js 的 timers 模块,你可以有效地控制代码的执行时机,实现各种定时任务和异步控制流程。

Java FileNode.js 内置模块