VUE实践优化:轮询机制与代码结构升级

2023-12-19

前言

我们之前探讨过,对于包含处理状态的表格数据,我们可以通过轮询的方式进行处理( 轮询更新进度条:JavaScript中的定时器和异步编程技巧 )。然而,当我们离开页面时,定时器仍会继续触发请求,这会造成资源的浪费,因为返回的数据并没有被渲染出来。

为了解决这个问题,我们需要实现以下要求:

  1. 最多只能同时存在一个轮询的定时器。
  2. 当用户离开页面时,定时器应被关闭。
  3. 当用户重新进入页面时,如果仍有数据正在处理中,应重新启动轮询。
  4. 轮询应能跨页面、跨显示数量。

实现

为了实现上述要求,我们可以采取以下步骤:

  1. 在全局范围内定义一个唯一的定时器变量,例如 running_task_timer
  2. 在开始轮询之前,检查 running_task_timer 是否已存在。如果存在,则清除该定时器并停止轮询。
  3. 如果需要启动轮询,首先检查页面是否处于激活状态。如果不在激活状态,则不启动轮询。
  4. 启动轮询时,设置 running_task_timer 为定时器的ID,并开始轮询处理。
  5. 当用户离开页面时,清除 running_task_timer 并停止轮询。
  6. 当用户重新进入页面时,检查是否有正在处理的数据。如果有,则重新设置 running_task_timer 并启动轮询。
  7. 在轮询处理中,检查页面是否处于激活状态。如果不在激活状态,则暂停轮询处理。
  8. 在轮询处理完成时,检查是否有新的数据需要处理。如果有,则重新设置 running_task_timer 并启动轮询。
  9. 通过上述步骤,我们可以确保同时只有一个轮询的定时器存在,并在用户离开页面时关闭定时器。当用户重新进入页面时,如果仍有数据正在处理中,可以重新启动轮询。同时,轮询的处理可以跨页面、跨显示数量进行。
<template>
  <div>
    <el-table :data="tableData">
      <el-table-column prop="id" label="任务ID" />
      <el-table-column prop="name" label="任务名称" />
      <el-table-column prop="status" label="任务状态" />
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button @click="reloadTask(scope.row)">重新执行</el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>
<script>
export default {
  data() {
    return {
      tableData: [],
      running_task_timer: null,
      running_task_list: [],
    };
  },
  created() {
    this.getData();
  },
  beforeDestroy() {
    this.clearMyInterval();
  },
  methods: {
    getData() {
      axios
        .get(url, query)
        .then(res => {
          if (res.status === 200) {
            tableData = res.data.data;
            this.addRunningTask();
          }
        })
        .catch(error => alert(error));
    },

    addRunningTask() {
      this.running_task_list = [];
      this.tableData.forEach(item => {
        if (item.status === 'RUNNING') this.running_task_list.push(item);
      });
      this.running_task_list.length ? this.startInterval() : this.clearMyInterval();
    },

    startInterval() {
      const _this = this;
      this.clearMyInterval();
      this.running_task_timer = setInterval(() => _this.getData, 1000);
    },

    clearMyInterval() {
      if (this.running_task_timer !== null) clearInterval(this.running_task_timer);
    },

    reloadTask(row) {
      row.status = 'BEGIN';
      axios
        .put(url, { id: row.id })
        .then(res => {
          if (res.status === 200) this.getData();
        })
        .catch(err => {
          alert(err);
          row.status = 'DONE';
        });
    },
  },
};
</script>

数据定义

  • tableData : 这是一个数组,用于存储从服务器获取的表格数据。
  • running_task_timer : 这是一个定时器变量,用于轮询正在运行的任务。
  • running_task_list : 这是一个数组,用于存储状态为“RUNNING”的任务。

生命周期钩子

  • created() : 当组件被创建时,它调用 getData() 方法来获取数据。
  • beforeDestroy() : 当组件即将被销毁时,它调用 clearMyInterval() 方法来清除定时器,以避免资源浪费。

方法

  • getData() : 使用 axios 发送 GET 请求来获取数据。如果响应的状态码是 200,它将更新 tableData 并调用 addRunningTask() 方法。
  • addRunningTask() : 遍历 tableData ,找出状态为“RUNNING”的任务,并将它们存储在 running_task_list 中。如果 running_task_list 有内容,则调用 startInterval() 方法来启动定时器;否则,调用 clearMyInterval() 方法清除定时器。
  • startInterval() : 首先调用 clearMyInterval() 来清除可能已经存在的定时器,然后设置一个新的定时器,每隔1秒调用 getData() 方法来轮询数据。
  • clearMyInterval() : 如果 running_task_timer 不为 null,则清除该定时器。
  • reloadTask(row) : 更新特定行的状态为“BEGIN”,并使用 axios 发送 PUT 请求来重新加载任务。如果响应的状态码是 200,则再次调用 getData() 方法。如果请求失败,它会将行的状态设置为“DONE”。

改进

提升性能:只更新修改项数据

<script>
export default {
  data() {
    return {
      tableData: [],
      running_task_timer: null,
      running_task_list: [],
    };
  },
  created() {
    this.getData();
  },
  beforeDestroy() {
    this.clearMyInterval();
  },
  methods: {
    getData() {
      axios
        .get(url, query)
        .then(res => {
          if (res.status === 200) {
            tableData = res.data.data;
            this.addRunningTask();
          }
        })
        .catch(error => alert(error));
    },

    addRunningTask() {
      this.running_task_list = [];
      this.tableData.forEach(item => {
        if (item.status === 'RUNNING') this.running_task_list.push(item);
      });
      if (this.running_task_list.length > 0) this.startInterval();
    },

    startInterval() {
      const _this = this;
      this.clearMyInterval();
      this.running_task_timer = setInterval(() => _this.updateTask, 1000);
    },

    clearMyInterval() {
      if (this.running_task_timer !== null) clearInterval(this.running_task_timer);
    },

    updateTask() {
      if (this.running_task_list.length === 0) this.clearMyInterval();
      const queryIds = [];
      this.running_task_list.forEach(item => queryIds.push(item.id));
      axios.get(url, { params: { ids: queryIds } }).then(res => {
        if (res.status === 200) {
          res.data.data.forEach(update_item => {
            this.running_task_list.forEach(item => {
              if (update_item.id === item.id) item = { ...update_item };
              // 去除已经完成的任务
              if (item.status !== 'RUNNING') this.running_task_list.splice(this.running_task_list.indexOf(item), 1);
            });
          });
        }
      });
    },

    reloadTask(row) {
      row.status = 'BEGIN';
      axios
        .put(url, { id: row.id })
        .then(res => {
          if (res.status === 200) this.getData();
        })
        .catch(err => {
          alert(err);
          row.status = 'DONE';
        });
    },
  },
};
</script>

更新机制的改进 :之前的代码可能存在一个性能问题,即定时器会不断轮询服务器,无论运行的条数多少,都会全量更新接口返回的数据,这可能导致不必要的性能浪费。在新的代码中,我们通过在 updateTask 方法中只更新 running_task_list 中存储的需要更新的项,来避免了这一问题。任务完成后,从 running_task_list 中移除,从而在当前页更新完毕后停止轮询。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VUE实践优化:轮询机制与代码结构升级 的相关文章

  • 如何减少顶点图中折线图的线条粗细

    我在角度项目中使用 Apex 图表 我在那里实现了时间序列图表 但无法减少折线图中的 线条粗细 这是我的配置 public initChartData void this series this response data data thi
  • 在反应中将索引从一个函数传递到另一个函数

    我有一个项目列表 单击删除按钮后该项目将被删除 我知道执行此操作的步骤 但我不知道如何将密钥传递到 dlt item 范围 http jsfiddle net 3Ley7uac 1 http jsfiddle net 3Ley7uac 1
  • 如何在 Rollup 中配置从多个输入文件仅生成单个输出文件?

    配置Rollupjs生成库时 如果输入是由多个javascript文件组成的数组 我们如何才能将这些输入生成为一个输出 js 文件呢 export const lgService input src app services livegiv
  • Node.js npm mssql 函数返回未定义

    我使用 mssql 和 node js 连接到 sql server 数据库 我试图通过将连接代码包装在具有一个查询参数的函数中来减少代码 当我从 router get 函数中的 with 调用该函数时 它返回未定义 任何帮助将非常感激 f
  • Leaflet.js setMaxBounds 忽略南界

    Using 传单 js http leafletjs com reference html对于开源地图项目 但我需要设置用户无法超越的特定界限 地图对象的 maxBounds 属性在北 东 西方向上按预期工作 但它让我永远向南滚动 在小提琴
  • 如何使错误冒泡,以便可以在同一个 try/catch 块中捕获它们?

    我有一个带有抛出错误的函数的对象 myObj ini function this f f function throw new Error 但我只想捕获创建对象的异常 try var o new myObj catch err alert
  • Ember 模型中的自定义请求 url

    我正在尝试将 Ember 数据与已构建的 REST api 一起使用 它适用于顶级路由 例如我在 api 端有课程路由 如下所示 app get courses app controllers courses findAll app get
  • 打开图层地图,经纬度获取地址

    我正在尝试获取带有经度和纬度的地址 城市 邮政编码 街道地址 但我不知道如何获取 我正在使用开放图层 当我单击地图的一部分时 会获取该位置的经度和纬度 有人有解决方案吗 div class map div
  • 在 Angular 中将图像 url 转换为 base64

    我正在努力尝试将给定的图像 url 转换为 base64 在我的例子中 我有一个带有图像路径的字符串 var imgUrl assets logoEmpresas empresa logoUrl 我如何直接将给定的图像网址转换为base64
  • JS 是否支持使用键函数而不是比较器进行排序?

    JavaScript 的array sort https developer mozilla org en US docs Web JavaScript Reference Global Objects Array sort Syntax方
  • Chrome DevTools 脚本黑盒不起作用

    我正在尝试使用 chrome devtools 的新功能 黑盒脚本 这篇 Chrome Devtools 文章列出了脚本黑盒功能 https developer chrome com devtools docs blackboxing wh
  • 有没有办法在 Blazor 中隐藏 div?

    我正在使用 Blazor 并且想在按下导航栏切换器图标时隐藏侧边栏 列表项崩溃了 但问题是 div 仍然存在 div class page div class sidebar div class nav top row pl 4 navba
  • 无法读取未定义的属性“messageHandlers”

    我想将 JavaScript 变量传递给 Swift 我在 JavaScript 中遇到错误并进行了搜索 但没有得到任何结果 错误是 类型错误 无法读取未定义的属性 messageHandlers 任何人都可以帮忙吗 我在 Xcode 中的
  • JavaScript 中 == 和 === 的区别[重复]

    这个问题在这里已经有答案了 有什么区别 and 在 JavaScript 中 我也见过 and 运营商 还有更多这样的运营商吗 看看这里 http longgoldenears blogspot com 2007 09 triple equ
  • 在 JavaScript 中给变量字符串加上引号

    我有一个 JavaScript 变量 var text http example com 文本可以是多个链接 如何在变量字符串周围放置 例如 我希望字符串看起来像这样 http example com var text http examp
  • 设备收到 GCM Android 通知但未显示

    尽管通知已在应用程序本身中注册 但我的 Ionic Android 应用程序的 GCM Cloud 消息通知未出现在我的设备的主屏幕中 我正在使用 npm 模块node gcm https www npmjs com package nod
  • Webpack 不包括 ProvidePlugins

    我正在开发一个小型试用 Web 应用程序 它使用 vue webpack 模板 https github com vuejs templates webpack https github com vuejs templates webpac
  • html5 canvas贝塞尔曲线获取所有点

    我喜欢从贝塞尔曲线中得到一些点 我发现 在javascript中查找三次贝塞尔曲线的所有点 https stackoverflow com questions 15397596 find all the points of a cubic
  • 如何提交表单 onkeyup 操作

    我正在尝试保存表格onkeyup行动 我是 jQuery 新手 这可能吗 我很感激任何帮助 编辑1 保存表单意味着保存到服务器 有没有办法增加0 2秒的延迟 此代码将在 keyup 上提交您的表单 element bind keyup fu
  • Material-UI 中 IconButton 的悬停效果

    图标按钮悬停 https i stack imgur com lsYHX png 这是我正在使用的 Material UI 中的 iconButton 正如您所看到的 当您将鼠标悬停在图标上时 图标周围有一个轻微的灰色边框 禁用此功能的属性

随机推荐