做定时任务,一定要用这个神库!!

沉浸式趣谈
• 阅读 50
  • Hey, 我是 沉浸式趣谈
  • 本文首发于【沉浸式趣谈】,我的个人博客 https://yaolifeng.com 也同步更新。
  • 转载请在文章开头注明出处和版权信息。
  • 如果本文对您有所帮助,请 点赞评论转发,支持一下,谢谢!

说实话,作为前端开发者,我们经常需要处理一些定时任务,比如轮询接口、定时刷新数据、自动登出等功能。

过去我总是用 setTimeoutsetInterval,但这些方案在复杂场景下并不够灵活。

我寻找了更可靠的方案,最终发现了 cron 这个 npm 包,为我的前端项目(特别是 Node.js 环境下运行的那部分)带来了专业级的定时任务能力。

cron 包:不只是个定时器

安装超级简单:

npm install cron

基础用法也很直观:

import { CronJob } from 'cron';

const job = new CronJob(
    '0 */30 * * * *', // 每30分钟执行一次
    function () {
        console.log('刷新用户数据...');
        // 这里放刷新数据的代码
    },
    null, // 完成时的回调
    true, // 是否立即启动
    'Asia/Shanghai' // 时区
);

看起来挺简单的,对吧?

但这个小包却能解决前端很多定时任务的痛点。

理解 cron 表达式,这个"魔法公式"

刚开始接触 cron 表达式时,我觉得这简直像某种加密代码。* * * * * * 这六个星号到底代表什么?

在 npm 的 cron 包中,表达式有六个位置(比传统的 cron 多一个),分别是:

秒 分 时 日 月 周

比如 0 0 9 * * 1 表示每周一早上 9 点整执行。

我找到一个特别好用的网站 crontab.guru 来验证表达式。

不过注意,那个网站是 5 位的表达式,少了"秒"这个位置,所以用的时候需要自己在前面加上秒的设置。

月份和星期几还可以用名称来表示,更直观:

// 每周一、三、五的下午5点执行
const job = new CronJob('0 0 17 * * mon,wed,fri', function () {
    console.log('工作日提醒');
});

前端开发中的实用场景

作为前端开发者,我在这些场景中发现 cron 特别有用:

1. 在 Next.js/Nuxt.js 等同构应用中刷新数据缓存

// 每小时刷新一次产品数据缓存
const cacheRefreshJob = new CronJob(
    '0 0 * * * *',
    async function () {
        try {
            const newData = await fetchProductData();
            updateProductCache(newData);
            console.log('产品数据缓存已更新');
        } catch (error) {
            console.error('刷新缓存失败:', error);
        }
    },
    null,
    true,
    'Asia/Shanghai'
);

2. Electron 应用中的定时任务

// 在 Electron 应用中每5分钟同步一次本地数据到云端
const syncJob = new CronJob(
    '0 */5 * * * *',
    async function () {
        if (navigator.onLine) {
            // 检查网络连接
            try {
                await syncDataToCloud();
                sendNotification('数据已同步');
            } catch (err) {
                console.error('同步失败:', err);
            }
        }
    },
    null,
    true
);

3. 定时检查用户会话状态

// 每分钟检查一次用户活动状态,30分钟无活动自动登出
const sessionCheckJob = new CronJob(
    '0 * * * * *',
    function () {
        const lastActivity = getLastUserActivity();
        const now = new Date().getTime();

        if (now - lastActivity > 30 * 60 * 1000) {
            console.log('用户30分钟无活动,执行自动登出');
            logoutUser();
        }
    },
    null,
    true
);

踩过的那些坑

使用 cron 包时我踩过几个坑,分享给大家:

  1. 时区问题:有次我设置了一个定时提醒功能,但总是提前 8 小时触发。一查才发现是因为没设置时区。所以国内用户一定要设置 'Asia/Shanghai'
// 这样才会在中国时区的下午6点执行
const job = new CronJob('0 0 18 * * *', myFunction, null, true, 'Asia/Shanghai');
  1. this 指向问题:如果你用箭头函数作为回调,会发现无法访问 CronJob 实例的 this。
// 错误示范
const job = new CronJob('* * * * * *', () => {
    console.log('执行任务');
    this.stop(); // 这里的 this 不是 job 实例,会报错!
});

// 正确做法
const job = new CronJob('* * * * * *', function () {
    console.log('执行任务');
    this.stop(); // 这样才能正确访问 job 实例
});
  1. v3 版本变化:如果你从 v2 升级到 v3,要注意月份索引从 0-11 变成了 1-12。

实战案例:构建一个智能通知系统

这是我在一个电商前端项目中实现的一个功能,用 cron 来管理各种用户通知:

import { CronJob } from 'cron';
import { getUser, getUserPreferences } from './api/user';
import { sendNotification } from './utils/notification';

class NotificationManager {
    constructor() {
        this.jobs = [];
        this.initialize();
    }

    initialize() {
        // 新品上架提醒 - 每天早上9点
        this.jobs.push(
            new CronJob(
                '0 0 9 * * *',
                async () => {
                    if (!this.shouldSendNotification('newProducts')) return;

                    const newProducts = await this.fetchNewProducts();
                    if (newProducts.length > 0) {
                        sendNotification('新品上架', `今天有${newProducts.length}款新品上架啦!`);
                    }
                },
                null,
                true,
                'Asia/Shanghai'
            )
        );

        // 限时优惠提醒 - 每天中午12点和晚上8点
        this.jobs.push(
            new CronJob(
                '0 0 12,20 * * *',
                async () => {
                    if (!this.shouldSendNotification('promotions')) return;

                    const promotions = await this.fetchActivePromotions();
                    if (promotions.length > 0) {
                        sendNotification('限时优惠', '有新的限时优惠活动,点击查看详情!');
                    }
                },
                null,
                true,
                'Asia/Shanghai'
            )
        );

        // 购物车提醒 - 每周五下午5点提醒周末特价
        this.jobs.push(
            new CronJob(
                '0 0 17 * * 5',
                async () => {
                    if (!this.shouldSendNotification('cartReminder')) return;

                    const cartItems = await this.fetchUserCart();
                    if (cartItems.length > 0) {
                        sendNotification('周末将至', '别忘了查看购物车中的商品,周末特价即将开始!');
                    }
                },
                null,
                true,
                'Asia/Shanghai'
            )
        );

        console.log('通知系统已初始化');
    }

    async shouldSendNotification(type) {
        const user = getUser();
        if (!user) return false;

        const preferences = await getUserPreferences();
        return preferences?.[type] === true;
    }

    // 其他方法...

    stopAll() {
        this.jobs.forEach(job => job.stop());
        console.log('所有通知任务已停止');
    }
}

export const notificationManager = new NotificationManager();

写在最后

作为前端开发者,我们的工作不只是构建漂亮的界面,还需要处理各种复杂的交互和时序逻辑。

npm 的 cron 包为我们提供了一种专业而灵活的方式来处理定时任务,特别是在 Node.js 环境下运行的前端应用(如 SSR 框架、Electron 应用等)。

它让我们能够用简洁的表达式设定复杂的执行计划,帮助我们构建更加智能和用户友好的前端应用。

点赞
收藏
评论区
推荐文章
洛竹 洛竹
4年前
给 React Native 库添加 Example
本文翻译自,也夹杂了一些私货,如有帮助,请不吝点赞。你为ReactNative制作了一个闪亮的新库,现在该向全世界展示它。但是您需要添加一个示例应用程序,以便人们可以在安装之前进行尝试。有一个示例程序也能让你在开发时测试。这看起来很简单,真的是吗?不幸的是,它不是那么简单,并且可能会非常具有挑战性。我将描述我使用的过程,也许会对您有所帮助。请注意
Stella981 Stella981
3年前
Android原生编解码接口 MediaCodec 之——踩坑
版权声明:本文为博主原创文章,遵循CC4.0BYSA版权协议,转载请附上原文出处链接和本声明。本文链接:https://blog.csdn.net/gb702250823/article/details/81669684希望我们尊重每个人的成果,转载请标明出处:https://blog.csdn.net/gb702250823/a
Stella981 Stella981
3年前
Kafka 设计与原理详解 
Kafka设计与原理详解 一、Kafka简介本文综合了我之前写的kafka相关文章,可作为一个全面了解学习kafka的培训学习资料。1转载请注明出处: 本文链接(https://www.oschina.net/action/GoToLink?urlhttp%
Wesley13 Wesley13
3年前
FMDB源码阅读(—)
阅读目录1.前言2.FMDB的最基本流程(结合上面例子)3.总结4.参考文章【原】FMDB源码阅读(一)本文转载请注明出处——polobymulberry博客园回到顶部1.前言说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于FMDB组件我是一点都没用过。好在FMD
Stella981 Stella981
3年前
Linux日志安全分析技巧
0x00前言我正在整理一个项目,收集和汇总了一些应急响应案例(不断更新中)。GitHub地址:https://github.com/Bypass007/EmergencyResponseNotes本文主要介绍Linux日志分析的技巧,更多详细信息请访问Github地址,欢迎Star。0x01日志简介Lin
Wesley13 Wesley13
3年前
5点改善你的编程逻辑
编程逻辑是成为优秀开发人员的关键。也许,根据您的工作地点,您将使用更多算法。如果你是一名网页设计师,你可能不打算处理复杂的算法,但如果你是前端开发人员,可能会处理一些算法,如果你是一个后端开发人员,你会经常处理复杂算法。在这里,我将向您介绍5个点,_在我看来_,这些点有资源来改进我们的编程逻辑。本文适合所有人,如果我们设法开发出一个好的逻辑,我们
Stella981 Stella981
3年前
React Native 网络层分析
文:志俊(沪江Web前端)本文原创,转载请注明作者及出处在使用ReactNative开发中,我们熟练的采用JavaScript的方式发送请求的方式发送一个请求到服务端,但是处理这个请求的过程其实和处理Web应用中发送的请求的过程是不一样的。因为处理这个请求的目标不是浏览器,而是嵌入这个应用的原生操作系统。<!more
定时任务原理方案综述 | 京东云技术团队
本文主要介绍目前存在的定时任务处理解决方案。业务系统中存在众多的任务需要定时或定期执行,并且针对不同的系统架构也需要提供不同的解决方案。京东内部也提供了众多定时任务中间件来支持,总结当前各种定时任务原理,从定时任务基础原理、单机定时任务(单线程、多线程)、分布式定时任务介绍目前主流的定时任务的基本原理组成、优缺点等。希望能帮助读者深入理解定时任务具体的算法和实现方案。
沉浸式趣谈 沉浸式趣谈
1星期前
为什么 AI 总在 "靠谱" 和 "离谱" 之间反复横跳?
Hey,我是沉浸式趣谈本文首发于【沉浸式趣谈】,我的个人博客https://yaolifeng.com也同步更新。转载请在文章开头注明出处和版权信息。如果本文对您有所帮助,请点赞、评论、转发,支持一下,谢谢!AI真的懂你问的问题吗?AI—它可能是个「语言魔
沉浸式趣谈 沉浸式趣谈
4天前
从开发者到讲师,我第一次教跨行业AI写代码的心路历程
Hey,我是沉浸式趣谈本文首发于【沉浸式趣谈】,我的个人博客https://yaolifeng.com也同步更新。转载请在文章开头注明出处和版权信息。如果本文对您有所帮助,请点赞、评论、转发,支持一下,谢谢!最近经历了人生第一次当老师的经历,想和大家分享一
沉浸式趣谈
沉浸式趣谈
Lv1
👤 个人网站: https://yaolifeng.com ✍ 微信公众号【沉浸式趣谈】 🚀 前端 & 开源 | 🕵‍♂ 工具 | 🧹 代码强迫症患者 ⚙️ 独立开发出海必备网站: https://www.indietools.work 🐙 Github: https://github.com/yaolifeng0629 𝕏 Twitter: https://x.com/Immerse_code 🏹 远程工作猎人
文章
10
粉丝
0
获赞
0