Scheduling Tasks in Node.js with node-cron

Jack Misteli

This is the final part of a three-part series about creating an app that leverages the web Push API and cron-schedule. Click here, for the article about creating an installable PWA, and here for the article about the Push API.

Obviously, in this article, we’ll cover the cron-scheduling aspect of the app and we’ll be making use of node-cron to do that.

What are we building

We are building a simple progressive web app (PWA) which will remind me to take my pills every day πŸ’ŠπŸ’Š.

Our app will have a web server powered by Express.js. Express will push notifications to the clients which subscribed to the push notifications. Express will also serve the frontend for the app.

What We’ve Built so Far

So far, we created an installable Progressive Web App and an Express.js Server to serve our static files on http://localhost:3000 and push notifications to the frontend.

What We Want to Build

I want to take my πŸ’Š at 8:30am, 3:30pm and 11:15pm. To do so, we will use a task scheduler.

The Basic of Cron

Cron is (one of || the) most famous job scheduler out there. It is used in Unix-based operating systems.

Let’s say you have a very susceptible computer. You want to be sure you don’t forget its birthday. If we want to run echo "I love you πŸ’»" every year at a specific date (this will output β€˜I love you πŸ’»β€™ in whatever environment you scheduled it in).

Here is what it would look like in cron (try to guess when is my computer’s birthday).

# β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ minute (0 - 59)
# β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ hour (0 - 23)
# β”‚  β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of the month (1 - 31)
# β”‚  β”‚ β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ month (1 - 12)
# β”‚  β”‚ β”‚  β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ day of the week (0 - 6) (Sunday to Saturday;
# β”‚  β”‚ β”‚  β”‚ β”‚                                   7 is also Sunday on some systems)
# β”‚  β”‚ β”‚  β”‚ β”‚
# β”‚  β”‚ β”‚  β”‚ β”‚
# 10 8 23 9 * echo "I love you πŸ’»"

Every year, the 23rd of September at 8:10am the computer will get a lovely message. Please note that the date is military so if we want to celebrate the birthday at 8pm we would write:

# 10 20 23 9 * echo "I love you πŸ’»"

The wildcard sign * means any. In this example it means any day of the week. If we wrote:

# 10 20 23 9 1 echo "I love you πŸ’»"

It would only wish a happy birthday when the computer’s birthday is on a Monday. The wild card can be used anywhere. To run a command every hour we would do: 0 * * * *. You can translate that command into β€œRun command when minute === 0”. Every hour on Monday would be 0 * * * 1.

For our apps the cron jobs will be:

# Morning πŸ’Š
30 8 * * *
# Afternoon πŸ’Š
30 15 * * *
# Night πŸ’Š
15 23 * * *

Using node-cron

I didn’t choose node-cron over other Node.js cron-like libraries for any other reason that it works for what I need.

To register a task all we have to do is:

const cron = require('node-cron');
const sendBirthdayMessage = () => { console.log("I love you πŸ’»") };

// schedule takes two arguments, cron time and the task to call when we reach that time
cron.schedule('10 20 23 9 1', sendBirthdayMessage())

Let’s incorporate it in our app.

// Each subscription is connected to a client
const allSubscriptions = {}

const registerTasks = (subscription) => {
  const endpoint = subscription.endpoint;

  // My remote machine is on UTC time and I live in Japan so I made the appropriate calculation
  const morningTask = cron.schedule('30 23 * * *', () => {
    sendNotification(subscription, JSON.stringify({ timeOfDay: 'morning' }));
  });
  const afternoonTask = cron.schedule('30 6 * * *', () => {
    sendNotification(subscription, JSON.stringify({ timeOfDay: 'afternoon' }));
  });
  const nightTask = cron.schedule('15 14 * * *', () => {
    sendNotification(subscription, JSON.stringify({ timeOfDay: 'evening' }));
  });

  allSubscriptions[endpoint] = [morningTask, afternoonTask, nightTask];
};

app.post('/subscribe', (req, res) => {
  const subscription = req.body;
  registerTasks(subscription);
  res.send('subscribed!');
});


// Allows our client to unsubscribe
app.post('/unsubscribe', (req, res) => {
  const endpoint = req.body.endpoint;
  allSubscriptions[endpoint].forEach(task => {
    // destroy allows us to delete a task
    task.destroy();
  });
  delete allSubscriptions[endpoint];
});

✨ And that's it! We are finally done with the app, you can find the full code in this Github repository. ✨

  Tweet It

πŸ•΅ Search Results

πŸ”Ž Searching...

Sponsored by #native_company# β€” Learn More
#native_title# #native_desc#
#native_cta#