node-schedule可以在指定时间执行任务。
node-schedule基于的是时间,而非时间间隔,适合用在“在每月的第三个星期二”,“每个小时的20分和50分”执行一次的场景,但如果你想“每5分钟执行一次”,建议用setInterval。
计划基于cron-parser,format格式如下:
scheduleJob根据计划执行任务:
const schedule = require('node-schedule'); const j = schedule.scheduleJob('49 * * * *', function() { console.log('49分(例如19:49, 20:49)时执行 job'); }); const j2 = schedule.scheduleJob({hour: 17, minute: 24, dayOfWeek: 0}, function() { console.log('周日的 17:23 分执行 job'); }); const date = new Date(2019, 11, 21, 5, 30, 0); const j3 = schedule.scheduleJob(date, function() { console.log('可以指定具体时间,例如 2019-11-21 05:30:00'); });
RecurrenceRule循环执行任务,支持参数:second(0-59),minute(0-59),hour(0-23),date(1-31),month(0-11),year,dayOfWeek(0-6,0是周日):
const schedule = require('node-schedule'); const rule = new schedule.RecurrenceRule(); rule.minute = 9; const j4 = schedule.scheduleJob(rule, function() { console.log('每小时的09分执行 job'); }); const rule2 = new schedule.RecurrenceRule(); rule2.dayOfWeek = [0, new schedule.Range(4, 6)]; rule2.hour = 17; rule2.minute = 24; const j5 = schedule.scheduleJob(rule2, function() { console.log('每周四~周日的 17:24 执行 job'); });
注意,如果是整点的话,注意将minute显示设为0(second默认是0,不用显示设)否则会5:00pm,5:01pm,5:02pm每分钟都执行,这可能不是你想要的。
start,end设置起始,停止时间:
const schedule = require('node-schedule'); const startTime = new Date(Date.now() + 5000); const endTime = new Date(startTime.getTime() + 5000); const j6 = schedule.scheduleJob({ start: startTime, end: endTime, rule: '*/1 * * * * *' }, function(){ console.log('5秒后执行,10秒后停止。每秒都执行,所以共执行5次。'); });
job.cancel(reschedule)取消这个job,设置参数reschedule为true的话,将重新安排后续计划
job.cancelNext(reschedule)取消下一个job,设置参数reschedule为true的话,将重新安排后续计划
job.reschedule(spec)使用给定的规范spec重新安排计划,成功/失败返回true/false。
job.nextInvocation()返回下一次执行该job的Date,如果没有下一次,将返回null。
最后
实际并没有使用node-schedule,因为用pm2部署node项目,node-schedule会在每个进程都执行任务。可以限定死只在0号进程执行任务:
if (process.env.NODE_APP_INSTANCE === '0') { ... // 执行任务 }
但线上有多台服务器时,每台服务器的0号进程都会执行。
可以指定其中一台机器的IP,判IP一致才执行,有点麻烦,最终用公司的分布式任务调度,能解决问题就行,轮子是不是自己造的是次要的。