首页 > 其他分享 >Vue3中循环任务优化方案

Vue3中循环任务优化方案

时间:2023-06-14 13:11:58浏览次数:48  
标签:exec number delay 任务 循环 Vue3 now 优化 id

需求

在使用循环任务时,往往需要使用到setInterval方法。其接受三个参数,分别是 1.具体执行的函数 2.执行时间间隔 3.传递个函数的参数,并返回一个id,后续可以使用这个id来停止循环的执行。具体的使用可以查阅MDN
在实际开发中,很容易重复创建相同的interval实例,进行反复的执行,并且在轮询场景,如果间隔时间设置不当,往往上一条请求未完成,下一条执行又开始了。
并且在Vue3中,由于热更新的存在更容易导致不断的创建interval实例。
为了解决这个问题可以使用下面的方法

解决方案

useSchedule.ts

const _id = Date.now();

class Schedule {

  id: number;

  intervalId: number;

  /**
   * 待执行任务集合
   */
  tasks: Map<string, Task> = new Map<string, Task>();

  constructor(id: number) {
    this.id = id;
    this.intervalId = setInterval(() => {
          // 校验本Schedule是否有效 无效则直接销毁
          if (this.id !== _id) {
            this.destroy();
            return;
          }
          // 有效则遍历Task列表 找到合适的执行
          const now = Date.now();
          for (const task of this.tasks.values()) {
            task.tryExecute(now);
          }
        },
        1
    )
    console.log("Red_K.", `开始Schedule! id: ${this.id}, intervalId: ${this.intervalId}`)
  }

  setDelayTask(id: string, exec: Function, delay: number) {
    this.tasks.set(
        id,
        new Task(
            id,
            exec,
            () => {
              this.removeTask(id)
            },
            "Delay",
            delay
        ));
  }

  setLoopTask(id: string, exec: Function, interval: number, delay: number = 0) {
    this.tasks.set(
        id,
        new Task(
            id,
            exec,
            () => {
              this.removeTask(id)
            },
            "Loop",
            delay,
            interval
        )
    )
  }

  setAsyncLoopTask(id: string, exec: Function, interval: number, delay: number = 0) {
    this.tasks.set(
        id,
        new Task(
            id,
            exec,
            () => {
              this.removeTask(id)
            },
            "Loop",
            delay,
            interval,
            false
        )
    )
  }

  removeTask(id: string) {
    this.tasks.delete(id);
    console.debug("Red_K.", `id: ${id} 的Task被移除!`)
  }

  private destroy() {
    clearInterval(this.intervalId);
    this.tasks.clear();
    console.log("Red_K.", `id: ${this.id}, intervalId: ${this.intervalId} 的Schedule示例被销毁!`)
  }
}

class Task {

  // 任务id
  id: string;

  // 具体运行函数
  exec: Function;

  // 任务类型
  type: "Delay" | "Loop";

  // 延时时间 延时任务中有效
  delay: number;

  // 间隔时间 循环任务中有效
  interval: number;

  // 是否正在运行
  isRunning: boolean = false;

  // 下次执行时间
  next: number;

  // 是否是同步任务。 尽在循环任务中有效,在循环任务中,如果前一个任务未执行完,又到其执行时间,跳过本次执行。
  isSync: boolean;

  // 延时任务在执行后需要移除自己
  removeSelf: Function;

  constructor(id: string,
              exec: Function,
              removeSelf: Function,
              type: "Delay" | "Loop",
              delay: number = 0,
              interval: number = 1000,
              isSync: boolean = true) {
    this.id = id;
    this.exec = exec;
    this.removeSelf = removeSelf;
    this.type = type;
    this.delay = delay;
    this.interval = interval;
    this.isSync = isSync;
    this.next = Date.now() + this.delay;
  }

  tryExecute(now: number) {
    if (now < this.next || (this.isSync && this.isRunning)) {
      return;
    }
    this.execute();
    if (this.type === 'Loop') {
      this.next = Date.now() + this.interval;
    }
    else if (this.type === 'Delay') {
      this.removeSelf();
    }
  }

  private async execute() {
    this.isRunning = true;
    await this.exec();
    this.isRunning = false;
  }

}
const schedule = new Schedule(_id);
export useSchedule(){
  return {
    schedule 
  }
}

具体使用案例

import { useSchedule } form '@/use/core/useSchedule'
const schedule = useSchedule().schedule;
// 案例1: 延时任务

schedule.setDelayTask(
  "testDelay",
  () => {console.log('10秒后执行')},
  10000
)

// 案例2: 同步循环任务
// 假设任务执行时长为10秒 但是间隔设置为5秒。则会在前一个任务执行完毕之后再去执行后一个任务。

let time = Date.now();
async function exec() {
  await new Promise<void>((resolve) => {
    setTimeout(() => {
      const now = Date.now();
      const pass = now - time;
      time = now;
      console.log(`测试同步循环任务, 间隔时间是 ${pass / 1000}s`)
      resolve();
    }, 5000)
  });
}

schedule.setLoopTask(
    "syncLoopTest",
    exec,
    3000
)

// 案例3: 异步循环任务
// 假设任务执行时长为10秒 但是间隔设置为5秒。则会在前一个任务执行完毕之后再去执行后一个任务。

let time = Date.now();
async function exec() {
  await new Promise<void>((resolve) => {
    setTimeout(() => {
      const now = Date.now();
      const pass = now - time;
      time = now;
      console.log(`测试异步循环任务, 间隔时间是 ${pass / 1000}s`)
      resolve();
    }, 5000)
  });
}

schedule.setAsyncLoopTask(
    "asyncLoopTest",
    exec,
    3000
)

结果:
案例一

案例二

案例三

标签:exec,number,delay,任务,循环,Vue3,now,优化,id
From: https://www.cnblogs.com/Scarlett-K/p/17479651.html

相关文章

  • 用Elevator优化AV1视频播放
    AOM会员Vimeo通过Elevator改善AV1解码过程中的丢帧和质量下降问题。感谢Google软件工程师姜健对本文做的技术审校。文/RaphaëlZumer译/刘俊技术审校/姜健https://medium.com/vimeo-engineering-blog/enhancing-av1-playback-with-elevator-6a2991c1aac0作为AV1编码标准的早......
  • 深度学习应用篇-元学习[14]:基于优化的元学习-MAML模型、LEO模型、Reptile模型
    深度学习应用篇-元学习[14]:基于优化的元学习-MAML模型、LEO模型、Reptile模型1.Model-AgnosticMeta-LearningModel-AgnosticMeta-Learning(MAML):与模型无关的元学习,可兼容于任何一种采用梯度下降算法的模型。MAML通过少量的数据寻找一个合适的初始值范围,从而改变梯度下降......
  • PyCharm 优化
    1.汉化File->Settings->Plugins(插件)在搜索栏中输入Chinese(Simplified)下载中文插件并安装重启PyCharm即出现汉化 ......
  • 查询配置数据库 视图 响应时长优化问题
    问题: 主数据库为oracle,配置数据库SqlServer,有个子页面查询SqlServer数据库视图,需要二十多秒才给响应处理方案:把查询分页数据的SQL 和查询分页计数的SQL异步处理原代码:page=iMpckService.getsympzkcSqlserver(params);//查询SQLserver数据库total=iMp......
  • 使用 ProcessBuilder API 优化你的流程
    ProcessBuilder介绍Java的ProcessAPI为开发者提供了执行操作系统命令的强大功能,但是某些API方法可能让你有些疑惑,没关系,这篇文章将详细介绍如何使用ProcessBuilderAPI来方便的操作系统命令。ProcessBuilder入门示例我们通过演示如何调用java-version命令输出JD......
  • jmeter线程组/随机顺序控制器/随机控制器/循环控制器/仅一次控制器的使用
    一.jmeter线程组的使用  根据http://api.qingyunke.com/api.php?key=free&appid=0&msg=%E9%B9%85%E9%B9%85%E9%B9%85拆分如图察看结果树:取样器结果:是返回有无调通  请求:发送的请求数据信息 响应数据:显示接口返回的数据  二。随机顺序控制器的使用使用随机顺序控制......
  • golang对于[]byte数组转string进行比较的优化
    当需要比较两个[]byte数组是否相等时有好几种方案,下面可以看出前三种方案都是优化过的,效率高的方案。packagemainimport( "bytes" "crypto/rand" mr"math/rand" "testing")funcStringEqual(nint,ffunc(a,b[]byte)bool){ buf:=make([]byte,1024) rand.......
  • 多种智能优化算法运行时间和不同函数测试对比附matlab代码
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • m基于FPGA的CRC循环冗余校验系统verilog实现,包含testbench
    1.算法仿真效果本系统进行了两个平台的开发,分别是:Vivado2019.2Quartusii18.0+ModelSim-Altera6.6dStarterEdition其中Vivado2019.2仿真结果如下:Quartusii18.0+ModelSim-Altera6.6dStarterEdition的测试结果如下:对比matlab结果:2.算法涉及理论知识概要CRC(CyclicR......
  • m基于FPGA的CRC循环冗余校验系统verilog实现,包含testbench
    1.算法仿真效果本系统进行了两个平台的开发,分别是: Vivado2019.2 Quartusii18.0+ModelSim-Altera6.6d StarterEdition 其中Vivado2019.2仿真结果如下:   Quartusii18.0+ModelSim-Altera6.6d StarterEdition的测试结果如下:  对比matlab结果:  2......