JavaScript 调度:setTimeout 和 setInterval

一、基础语法与核心差异

1. setTimeout:单次延迟执行

javascript 复制代码
const timerId = setTimeout(callback, delay, arg1, arg2, ...);  

• 功能 :在指定延迟(毫秒)后执行一次回调函数。

• 取消方法 :clearTimeout(timerId)。

2. setInterval:循环重复执行

javascript 复制代码
const intervalId = setInterval(callback, interval, arg1, arg2, ...);  

• 功能 :每隔固定时间重复执行回调函数。

• 取消方法 :clearInterval(intervalId)。

核心差异 :

• setTimeout:单次触发 ,适合延迟任务或递归实现循环。

• setInterval:固定间隔触发,适合周期性任务(需注意累积问题)。


二、实战技巧与经典问题

1. 用setTimeout模拟setInterval

由于setInterval可能因回调执行时间过长导致任务堆积 ,更安全的做法是递归调用setTimeout:

javascript 复制代码
function safeInterval(callback, interval) {  
  let timerId = null;  
  function execute() {  
    callback();  
    timerId = setTimeout(execute, interval); // 递归调用  
  }  
  timerId = setTimeout(execute, interval);  
  return () => clearTimeout(timerId); // 返回清除函数  
}  

此方法确保每次回调执行完毕后再重新计时,避免任务重叠。

2. 事件循环与时间精度问题

JavaScript是单线程的,定时器的回调会被推入任务队列,实际执行时间可能晚于预期:

javascript 复制代码
console.log("Start");  
setTimeout(() => console.log("Timeout"), 0);  
console.log("End");  
// 输出顺序:Start → End → Timeout  

即使延迟设为0,回调仍需等待主线程空闲。

3. 内存泄漏:忘记清除定时器

未及时调用clearTimeout或clearInterval会导致回调持续引用外部变量,内存无法释放:

javascript 复制代码
function startPolling() {  
  setInterval(() => {  
    fetchData(); // 持续运行,即使组件已销毁  
  }, 5000);  
}  

解决方案:在组件卸载或条件变更时主动清除定时器。


三、高级应用场景

1. 节流(Throttling)与防抖(Debouncing)

• 防抖:连续事件中只执行最后一次:

javascript 复制代码
function debounce(func, delay) {  
  let timerId;  
  return (...args) => {  
    clearTimeout(timerId);  
    timerId = setTimeout(() => func(...args), delay);  
  };  
}  

• 节流:固定时间内只执行一次:

javascript 复制代码
function throttle(func, interval) {  
  let lastTime = 0;  
  return (...args) => {  
    const now = Date.now();  
    if (now - lastTime >= interval) {  
      func(...args);  
      lastTime = now;  
    }  
  };  
}  
相关推荐
anew___22 分钟前
《从零手写操作系统 (20):ELF加载器——让OS读懂现代编译器》
java·服务器·前端
ss27323 分钟前
AI全栈实战 | 2.3-01 组件库实战:Element Plus 怎么搭出专业界面,过度封装为什么成维护负担
前端·javascript·elementui·vue
对空六课29 分钟前
动态按钮ID变化时的稳定埋点标识设计
前端·数据分析
福兮说33 分钟前
URL 编码的七个坑:c++ 传到后端变空格、%25 套娃、截断 emoji 直接报错
开发语言·前端·javascript·node.js·url
吴声子夜歌38 分钟前
Nginx应用与运维——Nginx Web服务应用实战(Python网站的搭建)
运维·前端·nginx
小的时候可菜了1 小时前
JS 异步的本质:从单线程到 thenable(一条进化链)
开发语言·前端·javascript
liangshanbo12151 小时前
Webpack vs Vite 底层原理高频追问的问题
前端·webpack·node.js
可乐鸡翅yeah_1 小时前
hls.js 配置 loadStartPosition,点播起始播放位置踩坑
开发语言·javascript·网络协议·ecmascript·m3u8在线
web打印社区1 小时前
Windows 网页静默打印设置步骤:客户端、防火墙与联调清单
开发语言·前端·javascript·chrome·pdf·ecmascript
恋猫de小郭2 小时前
KMP 又改了编译流程, Separate Compilation 禁止了 `commonMain` 的依赖穿透
android·前端·flutter