Start/stop 在 Nodejs Express 应用程序中单击按钮时的 cronjob

Start/stop cronjob on button click in Nodejs Express app

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

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

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 的新手。

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

提前致谢。

问题可能来自以下行:

    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

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

每次您点击 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)
    }
});