All Articles

Tasks scheduling in Node.js

In this post I will describe several ways of scheduling tasks in Node.js using standard JavaScript methods like setTimeout() and setInterval(), but also some libraries with a way more sophisticated scheduling configuration mechanisms.

Tasks scheduling is straightforward especially Node.js provides some standard methods simplifying that exercise. However, sometimes you may require to execute tasks at specific times (every Monday at 3AM or every weekday at 11:30AM) and then tasks scheduling becomes a way more challenging. In these cases, 3rd party library support will save us lots of time and effort.

One-off execution of a task

JavaScript has the setTimeout() method, which allows one-off execution of a function. The method accepts parameters as follows:

  • func - a function to be executed
  • delay - a number of milliseconds the execution of the given function should be delayed by. If this parameter is omitted or value 0 is used, the provided function will be executed as soon as possible.

An example of a message printed after 2 seconds:

setTimeout(() => console.log('Task completed'), 2000);

The setTimeout() method returns an identifier, which can be used to cancel a particular execution using the clearTimeout() method.

An example of a task cancelation:

const taksID = setTimeout(() => console.log('Task completed'), 2000);
clearTimeout(taskID);

Repetitive executions of a task

JavaScript has the setInterval() method, which allows continues execution of a function at specified intervals. The method accepts parameters as follows:

  • func - a function to be executed
  • delay - a number of milliseconds between executions of the given function. If the value of this parameter is below 10, a value of 10 is used.

An example of a message printed every 5 seconds:

setInterval(() => console.log('Task executed'), 5000);

The setInterval() method returns an identifier, which can be used to cancel a particular repetatice execution using the clearInterval() method.

An example of a repeative task cancelation:

const intervalID = setInterval(() => console.log('Task executed'), 5000);
clearInterval(intervalID);

Tasks execution at specific times

The setTimeout() and setIntervals() are straightforward to use. But what if I need to execute a task every Monday at 3AM or at midnight on the 3rd day of a month? In these cases, the default JavaScript methods are not so handy anymore. Of course, you can still use them, but you would need to calculate delay on your own. Say, you need to execute a task at midnight on the 3rd day of a month. You would need to calculate the number of milliseconds since now till next midnights on the 3rd and provide that value to setTimeout(). After a task execution, you would need to perform another calculation of a delay till midnight on the 3rd following month, and so on and on. That’s feasible but very time consuming and not a maintainable solution (every, even the smallest change of times, would require you to update and test your delay calculation code).

So what options do we have? Use of 3rd party Node.js module seems to be a very good idea to resolve that problem.

Personally, I use a lot node-cron, which is a Node.js scheduler using the cron syntax. I would recommend this library to everyone looking for a robust and configurable tasks scheduler.

Basic node-cron usage

const cron = require('cron')
const job = cron.job('* * * * *', () => console.log("Message every minute"))
job.start()

Explanation of the cron schedule expression

The cron schedule expression is very similar to crontab with an exception that it also accepts seconds field so you can schedule tasks to the second.

cron-with-seconds

Seconds
Value Description
0 - 59 Allowed values - seconds value
* Any value
, Value list separator
- Range values
/ Step values
Minutes
Value Description
0 - 59 Allowed values - minutes value
* Any value
, Value list separator
- Range values
/ Step values
Hours
Value Description
0 - 23 Allowed values - hours of 24-hour clock
* Any value
, Value list separator
- Range values
/ Step values
Day of month
Value Description
1 - 31 Allowed values - day of a month number
* Any value
, Value list separator
- Range values
/ Step values
Month
Value Description
1 - 12 Allowed values - month numbers: 1 for January, 2 for February etc.
JAN - DEC Allowed values as an alternative to the month numbers
* Any value
, Value list separator
- Range values
/ Step values
Day of week
Value Description
0 - 6 Allowed values - day numbers: 0 for Sunday, 1 for Monday etc.
SUN - SAT Allowed values as an alternative to the day numbers
* Any value
, Value list separator
- Range values
/ Step values

Some examples of cron schedules:

  • */5 * * * * * - runs every 5 seconds
  • */10 * * * * - runs every 10 minutes
  • 0 6-20/2 * * 1-5 - runs every second hour between 6AM and 8PM on weekdays (Monday through Friday)
  • 5 4 * * SUN - runs at 4:05 on every Sunday

Library testing

As you can see the node-cron library gives lots of flexibility in schedule times creation. However, sometimes it may be tricky to set up the right times. The library also provides a testing mechanism. One of the best ways of checking your schedule expression is to find out a number of the following execution dates. The following example will print out 5 dates of the scheduler expression as follows: 30 9-17/4 * * 1-5

const cron = require('cron')
const job = cron.job('30 9-17/4 * * 1-5')
console.log(job.nextDates(5).map(date => date.toString()))

That gives the following output (the example code run at 16:48 on 12 Feb 2019)

[ 'Tue Feb 12 2019 17:30:00 GMT+0000',
  'Wed Feb 13 2019 09:30:00 GMT+0000',
  'Wed Feb 13 2019 13:30:00 GMT+0000',
  'Wed Feb 13 2019 17:30:00 GMT+0000',
  'Thu Feb 14 2019 09:30:00 GMT+0000' ]

Test of this cron expression: 5 4 * * SUN give the following output:

[ 'Sun Feb 17 2019 04:05:00 GMT+0000',
  'Sun Feb 24 2019 04:05:00 GMT+0000',
  'Sun Mar 03 2019 04:05:00 GMT+0000',
  'Sun Mar 10 2019 04:05:00 GMT+0000',
  'Sun Mar 17 2019 04:05:00 GMT+0000' ]

Happy coding!