NestJS学习记录-NestJS任务调度

1、简单应用

文档地址:

中文:NestJS 中文网Nest 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的框架。 它使用渐进式 JavaScript,使用 TypeScript 构建,并结合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数式反应式编程)的元素。icon-default.png?t=O83Ahttps://nest.nodejs.cn/techniques/task-scheduling

英文:

Documentation | NestJS - A progressive Node.js frameworkNest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).icon-default.png?t=O83Ahttps://docs.nestjs.com/techniques/task-scheduling

1、安装依赖

npm install --save @nestjs/schedule

2、在app.module.ts文件中导入ScheduleModule 

ScheduleModule.forRoot()

此导入会初始化调用任务,注册所有代码中已经存在的延期任务(Timeout)、间隔任务(Interval)和其他形式的定时任务。

3、添加一个task.service

nest g service task

并加入以下代码,并且需要在app.module.ts中,providers中加入TaskService

import { Injectable } from '@nestjs/common';
import { Cron, CronExpression, Interval, Timeout } from '@nestjs/schedule';
import * as dayjs from 'dayjs';

@Injectable()
export class TaskService {

  @Cron('45 * * * * *', { name: "ExecCron" })
  execCron() {
    console.log(`ExecCron作业每分钟执行一次${dayjs(new Date()).format('YYYY-MM-DD hh:mm:ss')}`)
  }

  @Cron(CronExpression.EVERY_30_SECONDS)
  execSysCron() {
    console.log(`每30秒执行一次${dayjs(new Date()).format('YYYY-MM-DD hh:mm:ss')}`)
  }

  @Timeout(20000)
  timeoutTask() {
    console.log(`20s以后执行,只执行一次${dayjs(new Date()).format('YYYY-MM-DD hh:mm:ss')}`)
  }

  @Interval(20000)
  intervalTask() {
    console.log(`间隔20s执行一次${dayjs(new Date()).format('YYYY-MM-DD hh:mm:ss')}`)
  }
}

此时,使用npm start运行目录,会定时输出三种类型任务的执行结果:

2、动态应用

很多时候,我们需要灵活的添加定时任务,而不是在项目中集成定时任务。@nestjs/schedule包也提供了动态API,可以帮助我们更加灵活的处理定时任务,主要通过任务的name属性交互处理任务。

在app.controller.ts中导入@nestjs/schedule包下的SchedulerRegistry和cron包下的CronJob,

因为用到了日期格式化,我们把dayjs也一起倒入


import { SchedulerRegistry } from '@nestjs/schedule';
import { CronJob } from 'cron';
import * as dayjs from 'dayjs';

这里引用cron时,要根据 @nestjs/schedule包中引用的cron版本安装,cron版本不一致可能会引起代码报错。无法正常执行,通过查看文件node_modules->@nestjs->schedule->package.json,我们可以看到cron的版本,我们项目中也要安装此版本号的cron包。

在app.contrller.ts中添加以下代码

@Public()
  @ApiOperation({ summary: '停止延时任务' })
  @Get('stopTimeout/:name')
  stopTimeout(@Param('name') name: string) {
    const timeout = this.schedulerRegistry.getTimeout(name);
    clearTimeout(timeout);
  }

  @Public()
  @ApiOperation({ summary: '添加延时任务' })
  @Get('addTimeout/:name/:milliseconds')
  addTimeout(@Param('name') name: string, @Param('milliseconds', ParseIntPipe) milliseconds: number) {
    const callback = () => {
      //到时间后执行任务
      console.log(`Timeout ${name} executing after (${milliseconds})!`);
    };

    const timeout = setTimeout(callback, milliseconds);
    this.schedulerRegistry.addTimeout(name, timeout);
  }

  @Public()
  @ApiOperation({ summary: '删除延时任务', description: '通过任务name删除延时任务' })
  @Delete('delTimeout/:name')
  deleteTimeout(@Param('name') name: string) {
    this.schedulerRegistry.deleteTimeout(name);
    // console.log(`Timeout ${name} deleted!`);
    return `Timeout ${name} deleted!`
  }

  @Public()
  @ApiOperation({ summary: '获取所有延时任务' })
  @Get('getTimeout')
  getTimeouts() {
    const timeouts = this.schedulerRegistry.getTimeouts();
    // timeouts.forEach(key => console.log(`Timeout: ${key}`));
    return timeouts
  }

  @Public()
  @Get('stopInterval/:name')
  stopInterval(@Param('name') name: string) {
    const interval = this.schedulerRegistry.getInterval(name);
    clearInterval(interval);
  }

  @Public()
  @ApiOperation({ summary: '添加一个间隔任务' })
  @Get('addInterval/:name/:milliseconds')
  addInterval(@Param('name') name: string, @Param('milliseconds') milliseconds: number) {
    const callback = () => {
      //间隔执行任务
      console.log(`Interval ${name} executing at time (${milliseconds})!`);
    };

    const interval = setInterval(callback, milliseconds);
    this.schedulerRegistry.addInterval(name, interval);
  }

  @Public()
  @ApiOperation({ summary: '删除间隔任务' })
  @Delete('delInterval/:name')
  deleteInterval(@Param('name') name: string) {
    this.schedulerRegistry.deleteInterval(name);
    console.log(`Interval ${name} deleted!`);
  }

  @Public()
  @ApiOperation({ summary: '获取所有间隔任务' })
  @Get('getIntervals')
  getIntervals() {
    const intervals = this.schedulerRegistry.getIntervals();
    intervals.forEach(key => console.log(`Interval: ${key}`));
  }

  @Public()
  @ApiOperation({ summary: '停止cron任务' })
  @Get('stopJob/:name')
  stopJob(@Param("name") name: string) {
    const job = this.schedulerRegistry.getCronJob(name)
    if (job != null) {
      job.stop()
      console.log(job.lastDate())
      console.log(`${name}已停止`)
      return `${name}已停止`
    }
    return `${name}未找到`
  }

  @Public()
  @ApiOperation({ summary: '添加cron任务' })
  @Get('addJob/:name/:seconds')
  addCronJob(@Param('name') name: string, @Param('seconds') seconds: string) {
    const job = new CronJob(`${seconds} * * * * *`, () => {
      //执行内容,这里我们可以封装一些通用的任务,比如:调用一个处理数据的接口
      console.log(`job ${name} to run at ${dayjs(new Date()).format("YYYY-MM-DD hh:mm:ss")}!`);
    });

    this.schedulerRegistry.addCronJob(name, job);
    job.start();

    return `job ${name} added for each minute at ${seconds} seconds!`
  }

  @Public()
  @ApiOperation({ summary: '删除cron任务' })
  @Delete('delJob/:name')
  deleteCron(@Param('name') name: string) {
    this.schedulerRegistry.deleteCronJob(name);
    return `job ${name} deleted!`;
  }

  @Public()
  @ApiOperation({ summary: '获取所有cron任务' })
  @Get('getCrons')
  getCrons() {
    const jobs = this.schedulerRegistry.getCronJobs();
    let cronTasks = []
    jobs.forEach((value, key, map) => {
      cronTasks.push(key)
    });
    return cronTasks
  }

代码中,针对cron任务,间隔任务,延时任务分别做了增、删、停止(改)、查询。

这样我们可以结合我们自己的场景搭建一个单独的任务调度服务,用来处理我们可能遇到的所有定时任务的需求。

测试cron任务接口:

新增cron任务

获取所欲cron任务:

 停止一个cron任务

 停止后,我们可以看到,corn-task01不执行了

删除一个任务

 

删除后,我们再获取所有cron任务,发现corn-task01不见了

 以上是学习NestJS任务调度的整个过程,其实也是模拟了真实工作中遇到的任务调度需求。之前一直再用Hangfire做整个工作,有兴趣的也可以学习一下,有两个版本一个基于ASP.NET framework,一个基于.NET Core的。

官网地址:Hangfire – Background jobs and workers for .NET and .NET CoreAn easy way to perform background processing in .NET and .NET Core applications. No Windows Service or separate process required.icon-default.png?t=O83Ahttps://www.hangfire.io/

使用情况:

 我是通过接口添加不同任务,目前已经跑了50w+次任务了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值