1. 定时任务的类型
Nestjs中有三种任务类型:
addCronJob
: 用于周期性任务,基于 Cron 表达式addTimeout
: 用于一次性延迟任务addInterval
: 基于固定的时间间隔而不是Cron表达式
在 NestJS 中,addCronJob
、addTimeout
和 addInterval
是三种不同的定时任务管理方法,下面介绍下他们的区别和使用场景。
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!