Nestjs22之定时任务

1. 定时任务的类型

Nestjs中有三种任务类型:

  • addCronJob: 用于周期性任务,基于 Cron 表达式
  • addTimeout: 用于一次性延迟任务
  • addInterval: 基于固定的时间间隔而不是Cron表达式

在 NestJS 中,addCronJobaddTimeoutaddInterval 是三种不同的定时任务管理方法,下面介绍下他们的区别和使用场景。

2. 使用场景案例

2.1 addCronJob(基于 Cron 表达式的周期性任务)

2.1.1 功能

• 根据 Cron 表达式 按固定时间规则重复执行任务(如每天 8 点、每月的第 1 天)。 • 适合需要复杂时间调度的场景。

2.1.2 适用场景

  • 每天凌晨 3 点清理日志
  • 每周一上午 10 点发送周报
  • 每月最后一天生成账单
  • ...

2.1.3 代码示例

typescript 复制代码
import { SchedulerRegistry } from '@nestjs/schedule';
import { CronJob } from 'cron';

@Injectable()
export class CronService {
  constructor(private schedulerRegistry: SchedulerRegistry) {}

  // 添加 Cron 任务
  addDailyTask(jobName: string, cronExpression: string) {
    const job = new CronJob(cronExpression, () => {
      console.log('执行周期性任务');
    });

    this.schedulerRegistry.addCronJob(jobName, job);
    job.start();
  }

  // 删除 Cron 任务
  removeJob(jobName: string) {
    this.schedulerRegistry.deleteCronJob(jobName);
  }
}

2.2 addTimeout(一次性延迟任务)

2.2.1 功能

• 在指定延迟时间后 执行一次任务,之后自动销毁。 • 适合需要单次延迟触发的场景。

2.2.2 适用场景

• 用户下单后 30 分钟未支付自动取消订单。 • 5 秒后发送短信验证码。 • 10 分钟后提醒用户任务完成。

2.2.3 代码示例

typescript 复制代码
import { SchedulerRegistry } from '@nestjs/schedule';

@Injectable()
export class TimeoutService {
  constructor(private schedulerRegistry: SchedulerRegistry) {}

  // 添加延迟任务
  addDelayedTask(jobName: string, delayMs: number) {
    const timeout = setTimeout(() => {
      console.log('执行一次性任务');
    }, delayMs);

    this.schedulerRegistry.addTimeout(jobName, timeout);
  }

  // 取消任务
  cancelTask(jobName: string) {
    this.schedulerRegistry.deleteTimeout(jobName);
  }
}

2.3 addInterval(基于固定间隔的周期性任务)

2.3.1 功能

• 根据 固定时间间隔(如每隔 5 秒)重复执行任务。 • 适合需要简单周期性触发的场景。

2.3.2 适用场景

• 每隔 30 秒检查服务器状态。 • 每隔 10 分钟同步一次缓存数据。 • 每隔 1 小时刷新一次 API Token。

2.3.3 代码示例

typescript 复制代码
import { SchedulerRegistry } from '@nestjs/schedule';

@Injectable()
export class IntervalService {
  constructor(private schedulerRegistry: SchedulerRegistry) {}

  // 添加间隔任务
  addIntervalTask(jobName: string, intervalMs: number) {
    const interval = setInterval(() => {
      console.log('执行间隔任务');
    }, intervalMs);

    this.schedulerRegistry.addInterval(jobName, interval);
  }

  // 删除间隔任务
  removeInterval(jobName: string) {
    this.schedulerRegistry.deleteInterval(jobName);
  }
}

3. 总结

3.1 三者的核心区别对比

特性 addCronJob addTimeout addInterval
执行次数 周期性(按 Cron 表达式重复) 单次(延迟执行后销毁) 周期性(按固定间隔重复)
时间规则 Cron 表达式(如 0 3 * * * 延迟时间(如 30000 毫秒) 间隔时间(如 5000 毫秒)
任务管理 可手动启动/停止,需显式删除 执行后自动销毁,可提前取消 需显式删除以停止
底层实现 基于 node-cron 基于 Node.js 原生的 setTimeout 基于 Node.js 原生的 setInterval
适用场景 复杂时间规则(如每天、每周) 一次性延迟任务(如倒计时) 简单周期性任务(如轮询)
持久化支持 ❌ 任务重启后需重新注册 ❌ 任务重启后需重新注册 ❌ 任务重启后需重新注册
分布式系统兼容性 ❌ 单实例生效,多实例重复执行 ❌ 单实例生效,多实例重复执行 ❌ 单实例生效,多实例重复执行

3.2 如何选择?

  • 需要复杂时间规则addCronJob(如每天凌晨执行)。
  • 需要单次延迟任务addTimeout(如 30 分钟后取消订单)。
  • 需要简单重复任务addInterval(如每隔 5 秒检查状态)。
  • 需要分布式支持 → 改用 Bull + Redis 或数据库任务队列。

通过对比合理选择自己的使用场景,希望对大家有所帮助,如有错误,请指正O^O!

相关推荐
程序员爱钓鱼1 小时前
Node.js 编程实战:文件读写操作
前端·后端·node.js
PineappleCoder1 小时前
工程化必备!SVG 雪碧图的最佳实践:ID 引用 + 缓存友好,无需手动算坐标
前端·性能优化
JIngJaneIL2 小时前
基于springboot + vue古城景区管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
敲敲了个代码2 小时前
隐式类型转换:哈基米 == 猫 ? true :false
开发语言·前端·javascript·学习·面试·web
澄江静如练_2 小时前
列表渲染(v-for)
前端·javascript·vue.js
JustHappy2 小时前
「chrome extensions🛠️」我写了一个超级简单的浏览器插件Vue开发模板
前端·javascript·github
Loo国昌3 小时前
Vue 3 前端工程化:架构、核心原理与生产实践
前端·vue.js·架构
sg_knight3 小时前
拥抱未来:ECMAScript Modules (ESM) 深度解析
开发语言·前端·javascript·vue·ecmascript·web·esm
LYFlied3 小时前
【每日算法】LeetCode 17. 电话号码的字母组合
前端·算法·leetcode·面试·职场和发展