Categories
Node.js Tips

Node.js Tips — Closing Connections, Templates, and Dates

Spread the love

Like any kind of apps, there are difficult issues to solve when we write Node apps.

In this article, we’ll look at some solutions to common problems when writing Node apps.

Custom Validation Using 2 Fields with Mongoose

To do custom validation using 2 fields with Mongoose, we can create a custom schema and a validation function and pass that as the value of a field in the object we pass into the Schema constructor.

For instance, we can write:

const dateRangeSchema = {
  startDate: { type: Date },
  endDate: { type: Date }
};

const checkDates = (value) => {
  return value.endDate < value.startDate;
}

const schema = new Schema({
  dateRange: { type: dateRangeSchema, validate: checkDates }
});

We created the dateRangeSchema with the startDate and endDate fields.

Also, we created thew checkDates function to return the date range.

And then we pass both into the object to specify the data type for a field.

We can also pass in a callback to validate by writing:

schema.pre('validate', function(next) {
  if (this.startDate > this.endDate) {
    next(new Error('start date is after the end date'));
  } else {
    next();
  }
});

We get the startDate and endDate values from the model and call next with an error if the start date is bigger than the end date.

Otherwise, we call next with nothing to proceed as normal.

Format a Date Coming from MongoDB

We can format a date coming from MongoDB with the toDateString method.

For instance, we can write:

Schema
  .virtual('date')
  .get(function() {
    return this._id.generationTime.toDateString();
  });

We can also use the moment.js library to make our lives easier.

For instance, we can write:

Schema
  .virtual('date')
  .get(function() {
    return moment(this._id.generationTime).format("YYYY-MM-DD HH:mm");
  });

We called the format method to format the moment object created from the moment function into the date format we want.

It’s returned as a string.

Variable in Class Name in Jade/Pug Template

We can interpolate a string into a Jade/Pug template by writing:

div(class="language-#{session.language}")

Listen to All Interfaces Instead of Localhost Only in an Express App

We listen to all interfaces in an Express app by passing in '0.0.0.0' as the 2nd argument of listen.

For instance, we can write:

const express = require('express');
const app = express();
app.listen(3000, '0.0.0.0');

Accessing EJS Variable in Javascript Logic

If we have a route that renders an EJS template, we can render the variable that’s passed in from the render method.

For instance, we can write:

app.get("/post/:title, (req, res) => {
  //...
  res.render("post", { title, description });
}

to create our route,

Then in our EJS template, we can write:

<% if (title) { %>
     <h2>Post</h2>
     <script>
        const postTitle = <%= title %>
     </script>
<% } %>

We get the title from the object in the 2nd argument.

Then we interpolate the title into the template.

Now we can assign that to a variable.

End an Express.js POST Response

We call res.end to end the response to end the response.

For instance, we can write:

res.end('hello');

Or we can render a template and then call res.end :

res.render('some.template');
res.end();

Shut Down an Express Server Gracefully When Its Process Is Killed

We can listen to the SIGTERM and SIGINT signals and then run our code in the handler for those signals and close the server in the callback.

For instance, we can write:

const express = require('express');

const app = express();

app.get('/', (req, res) => res.send('hello'});

const server = app.listen(3000);

setInterval(() => server.getConnections((err, connections) =>  {
  console.log(`${connections} connections currently open`)
}), 1000);

process.on('SIGTERM', shutDown);
process.on('SIGINT', shutDown);

let connections = [];

server.on('connection', connection => {
  connections.push(connection);
  connection.on('close', () => {
    connections = connections.filter(curr => curr !== connection)
  });
});

const shutDown = () => {
  server.close(() => {
    process.exit(0);
  });

  setTimeout(() => {
    process.exit(1);
  }, 10000);

  connections.forEach(curr => curr.end());
  setTimeout(() => connections.forEach(curr => curr.destroy()), 5000);
}

We listen to the SIGTERM and SIGINT signals with the process.on method.

We pass in the shutDown function, where we call server.close to close the connections.

We also exit with code 1 after 10 seconds if the connections aren’t closed successfully.

The connections are stored in the connections array and call end to close each connection.

We also call destroy to destroy the connections after 5 seconds.

The connections cames from the connection event handler where we pushed new connection objects into the connections array.

We also add the close handler with the filter method.

Conclusion

We can validate multiple fields concurrently with Mongoose.

Also, we can shut down connections gracefully.

We can also format the date coming from MongoDB.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *