IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> javascript随笔 -- 定时器清理终篇 -> 正文阅读

[JavaScript知识库]javascript随笔 -- 定时器清理终篇

javascript随笔 -- 定时器清理终篇

问题背景

产品经理:实现一个列表(包含:人员名称、在线状态 等字段),每 10 秒更新一次列表中 在线状态 字段。
开发 SE: 后台实现推送比较复杂,项目要求紧急上线,临时采用前台定时器查询方案。
开发实现:列表查询页面( personList.vue )调用列表查询接口( /queryListApi ),前台查询成功后,判断有数据,则开启 setTimeout 10 秒查询列表接口,更新列表状态数据。

具体代码如下:

<script>
// 项目基于 Vue 框架
export default {
  data() {
    return {
      personList: [],
      timer: null
    }
  },
  created() {
    this.queryList()
  },
  beforeDestory() {
    this.clearQueryListTimer()
  },
  methods: {
    queryList() {
      axios.get('/queryListApi').then(data => {
        if (data && data.length) {
          this.personList = [...data]
          this.clearQueryListTimer()
          this.timer = setTimeout(() => {
            this.queryList()
          }, 10000)
        }
      })
    },
    clearQueryListTimer() {
      this.timer && clearTimeout(this.timer)
      this.timer = null
    }
  }
}
</script>

开发自测发现问题:

  1. 当前页面接口请求 pending 时,切换路由到其他页面,回调中的定时器会仍然执行;
  2. 快速切换当前页面与其他页面,定时器运行多个,接口频繁多次调用;
  3. 页面卡顿,内存泄露;

问题分析

  1. 接口 pending 状态时,切换路由,触发 beforeDestory ,clearTimeout 清理早了,接口请求成功后还是会开启定时器;
  2. 应该避免暴力切换路由,添加防抖操作;
  3. 从结果来看,定时器有漏清理问题,导致内存泄露,问题根因指向了 this.timer;
  4. this.timer 变量会 10 秒修改一次,clearTimeout 清理的 this.timer 指向不明确;

解决方案

  1. 在定时器回调中,获取当前页面路由,判断是否为 personList.vue 页面,不是则清理定时器;
  2. 对路由切换添加防抖操作,在接口请求时添加全局 loading 效果;
  3. 将 this.timer 存到一个数组 timerArr 中,将 timerArr 存到 session 里面;
    清理时,在 session 中取出 timerArr,遍历 timerArr ,触发 clearTimeout;

具体代码如下:

<script>
// 项目基于 Vue 框架
export default {
  data() {
    return {
      personList: [],
      timer: null,
      loading: false
    }
  },
  created() {
    console.log(this.$route.path)
    this.queryList()
  },
  beforeDestory() {
    this.clearQueryListTimer()
  },
  methods: {
    queryList() {
      // loading 效果添加
      this.loading = true
      axios.get('/queryListApi').then(data => {
        this.loading = false
        if (data && data.length) {
          this.personList = [...data]
          this.clearQueryListTimer()
          this.timer = setTimeout(() => {
            // 路由判断添加
            if (this.$route.path !== '/personList') {
              this.clearQueryListTimer()
              return
            }
            this.queryList()
          }, 10000)
          this.updateTimerArr(this.timer)
        }
      })
    },
    updateTimerArr(id) {
      let timerArr = JSON.parse(sessionStorage.getItem('timerArr') || '[]')
      timerArr.push(id)
      sessionStorage.setItem('timerArr', JSON.stringify(timerArr))
    },
    clearQueryListTimer() {
      let timerArr = JSON.parse(sessionStorage.getItem('timerArr') || '[]')
      if (timerArr.length) {
        for (let i = 0; i < timerArr.length; i++) {
          clearTimeout(timerArr[i])
        }
        sessionStorage.setItem('timerArr', '[]')
      }
    }
  }
}
</script>

定时器清理总结

  1. 项目中能不用定时器,就不要使用定时器,无法避免的情况下,一定要做好定时器清理;
  2. 碰到任务状态更新、进度条开发等需求,采用 websocket ,后台推送、前台更新最优,避免使用前台轮询;
  3. 像 轮播图 等简单的定时器需求,可以在页面 生命周期 中清理定时器;
  4. 接口 pending 导致 beforeDestory 生命周期被绕过,定时器清理可以搭配 路由判断 一块使用;
  5. 复杂场景(循环微任务接口查询等),将开启的定时器 timer 拼成数组,存至 session 或全局变量中,循环遍历清理;
  6. 如果老项目中已有很多定时器书写不规范,临时规避方案:
    // 暴力清理全局定时器
    let timer = setInterval(() => {}, 1000);
    for (let i = 0; i < timer + 1; i++) {
        clearInterval(i);
    }
    let timer2 = setTimeout(() => {}, 1000);
    for (let j = 0; j < timer2 + 1; j++) {
        clearTimeout(j);
    }
    
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-13 09:11:00  更:2021-09-13 09:12:43 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 12:36:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计