在 Nodejs Express 应用程序中单击按钮时启动/停止 cronjob

Posted

技术标签:

【中文标题】在 Nodejs Express 应用程序中单击按钮时启动/停止 cronjob【英文标题】:Start/stop cronjob on button click in Nodejs Express app 【发布时间】:2021-07-03 08:10:06 【问题描述】:

我一直在做一个项目,当用户单击前端的按钮时,它需要启动和停止 cron 调度程序。基本上,当用户单击按钮时,cron 作业将启动。单击停止按钮将停止计时器。就这么简单。

为了实现这一点,我在单击按钮时向 Nodejs/Express 后端发出发布请求,这会触发调度程序的启动/停止功能。这是端点的样子:

const cron = require('node-cron');

router.post('/scheduler', async (req, res) => 

    // gets the id from the button
    const id = req.body.id;

    try
         // finds the scheduler data from the MongoDB
         const scheduler = await Scheduler.find( _id: id );

         // checks whether there is a scheduler or not
         if ( !scheduler  ) 
             return res.json(
                  error: 'No scheduler found.'
             );
         

         // creates the cronjob instance with startScheduler 
         const task = cron.schedule('*/10 * * * * *', () =>  
              console.log('test cronjob running every 10secs');
         , 
              scheduled: false
         );

         // checks if the scheduler is already running or not. If it is then it stops the scheduler
         if ( scheduler.isRunning ) 

             // scheduler stopped
             task.stop();

             return res.json(
                  message: 'Scheduler stopped!'
             );
         

         // starts the scheduler
         task.start();

         res.json(
              message: 'Scheduler started!'
         );

    catch(e) 
         console.log(e)
    
);

现在调度程序运行良好,但不会在第二次单击按钮时停止。它继续运行。我觉得我没有在正确的地方打电话给task.start()task.stop()。而且我不知道正确的地方在哪里。我实际上是 cronjobs 的新手。

如果有人告诉我我做错了什么,那就太好了。

提前致谢。

【问题讨论】:

【参考方案1】:

每次您点击scheduler api 时,都会创建一个cron-job 的新实例,并且您正在停止新定义的cron-job 实例 而不是上一个

解决方案是定义 cron-job 超出路由器范围,这样每当您点击scheduler api 时,实例都不会改变

像这样:

const cron = require('node-cron');

// creates the cronjob instance with startScheduler 
const task = cron.schedule('*/10 * * * * *', () =>  
    console.log('test cronjob running every 10secs');
, 
    scheduled: false
);

router.post('/scheduler', async (req, res) => 

    // gets the id from the button
    const id = req.body.id;

    try
         // finds the scheduler data from the MongoDB
         const scheduler = await Scheduler.find( _id: id );

         // checks whether there is a scheduler or not
         if ( !scheduler  ) 
             return res.json(
                  error: 'No scheduler found.'
             );
         

         // checks if the scheduler is already running or not. If it is then it stops the scheduler
         if ( scheduler.isRunning ) 

             // scheduler stopped
             task.stop();

             return res.json(
                  message: 'Scheduler stopped!'
             );
         

         // starts the scheduler
         task.start();

         res.json(
              message: 'Scheduler started!'
         );

    catch(e) 
         console.log(e)
    
);

【讨论】:

嘿伙计。你知道我们是否可以创建多个可以通过它们的 ID 停止的 cron 作业吗?例如,我启动了 cron 作业 1 和 2,现在我只想停止 cron 作业 2。我怎样才能只停止那个 cron 作业? 定义另一个超出范围的 cronjob,就像 Abhishek 为第一个 cronjob 建议的那样。 另外不要忘记在每次启动/停止后更新您的数据库中的调度程序运行状态 @Zak 这就是声明 'const task' 的用途,控制 cronjob 实例。因此,您将复制声明,但将第 2、3、4 个 cronjob 变量命名为“const task2、const task3、const task4”(或者更好的是,适当命名它们,即如果分配给 task2 的 cronjob 是“发送一些电子邮件” ,你应该把它命名为'const emailCron'。然后你可以通过对emailCron的引用来操作那个特定的对象,即:emailCron.stop();或emailCron.starat();hth! @RobLittle 非常感谢。我现在明白了!【参考方案2】:

问题可能出在下面一行:

    const task = cron.schedule('*/10 * * * * *', () =>  

实际上,如果您阅读 node-cron 的源代码,它会创建一个新任务并使用新的调度程序: https://github.com/node-cron/node-cron/blob/fbc403930ab3165ffef7d53387a29af92670dfea/src/node-cron.js#L29

    function schedule(expression, func, options) 
        let task = createTask(expression, func, options);
        storage.save(task);
        return task;
    

(内部使用:https://github.com/node-cron/node-cron/blob/fbc403930ab3165ffef7d53387a29af92670dfea/src/scheduled-task.js#L7:

    let task = new Task(func);
    let scheduler = new Scheduler(cronExpression, options.timezone, options.recoverMissedExecutions);

所以,当你打电话时:

    task.stop();

据我了解,您所做的是调用全新任务的方法“停止”,而不是您第一次单击按钮时启动的任务的方法停止。

从您的代码来看,问题在于您在使用任务时实际上并没有使用调度程序。

PS: 该模块还公开了一个函数,可让您从其存储中检索任务:https://github.com/node-cron/node-cron/blob/fbc403930ab3165ffef7d53387a29af92670dfea/src/node-cron.js#L58

但由于我没有找到任何关于它的文档,我不建议使用它。

【讨论】:

嘿,谢谢你的时间。所以它有点令人困惑,因为我的模型也被命名为调度程序。哈哈。但是我从您的回答中了解到的是,第二次按钮单击实际上会创建另一个任务,而不是停止前一个任务。所以我认为我可以在这里做两件事:1: put that task variable somewhere where it won't create the second time.2: call getTask() function but there's no documentation on it. 我认为我应该选择 1。你知道如何在整个设置中实现这一点吗?

以上是关于在 Nodejs Express 应用程序中单击按钮时启动/停止 cronjob的主要内容,如果未能解决你的问题,请参考以下文章

Nodejs/Express 保存从 web 客户端选择头像并直接保存到 MySQL 数据库

NodeJS Express 异步/等待

Nodejs Express 重定向不起作用

如何捕捉这个错误 NodeJs/Express?

NodeJS+Express+MySQL开发小记:服务器部署

如何使用 nodejs / express 将数据存储在 mongodb 中?