Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
Like any kind of apps, JavaScript apps also have to be written well.
Otherwise, we run into all kinds of issues later on.
In this article, we’ll look at some best practices we should follow when writing Node apps.
Handle Errors and Exceptions Properly
We should handle errors and exceptions properly on our Express app.
In synchronous code or an async function, we can use try-catch:
async function foo() {
try {
const baz = await bar()
return baz
} catch (err) {
console.error(err);
}
}
If we want to catch errors in middleware, we can create our own middleware to catch errors.
For example, we can write:
function errorHandler(err, req, res, next) {
console.error(err)
res.status(err.status || 500).send(err.message)
}
router.use(errorHandler)
We have the errorHandler
middleware to catch errors from other middleware that are added before it.
Then we can call router.use
or app.use
with the errorHandler
to handle the error.
Watch Out For Memory Leaks
We should watch for memory leaks so that our app doesn’t run out of memory.
Increasing memory usage is bad if it happens continuously.
This means that the app keeps using memory.
There’re apps like Sematext Agent Express module which lets us watch the CPU and memory usage of our app.
With this package, we can integrate it with:
const { stMonitor, stLogger, stHttpLoggerMiddleware } =
require('sematext-agent-express')
stMonitor.start()
const express = require('express')
const app = express()
app.use(stHttpLoggerMiddleware)
We just call stMonitor.start()
to start monitoring with Sematext when our app starts.
Other tools like Scout also shows us the memory usage of each line of code.
We can see which ones are using more memory and the times that uses more memory.
These can also monitor each request for performance issues.
JavaScript
We can improve our Express app’s JavaScript code to make it easier to test and maintain.
Pure Functions
Pure functions are functions that let returns something and don’t change any outer state.
If we pass in the same parameters to them, then they’ll always return the same value.
This makes their behavior predictable and simplifies everyone’s lives.
We can create new objects instead of mutating existing objects with pie functions.
Some examples of pure functions in JavaScript include the array instance’s map
and filter
methods and many more.
Object Parameters
To make working with parameters, we should reduce the number of parameters in our function.
One easy way to do it is to add an object parameter to our function.
Then we can use destructuring to destructure the properties into variables.
This way, we won’t have to worry about the order of the parameters.
For example, we can write:
const foo = ({ a, b, c }) => {
const sum = a + b + c;
return sum;
}
We just take the a
, b
, and c
parameters and use them as variables.
Write Tests
Tests are great for catching regressions.
This way, if we change our code, we can have peace of mind that we didn’t kill any existing code if the existing tests pass.
With JavaScript, there are many test frameworks, including Mocha, Chai, Jasmine, and Jest.
We can use any of them to run test.
With Chai, we can write:
const chai = require('chai')
const expect = chai.expect
const foo = require('./src/foo')
describe('foo', function () {
it('should be a function', function () {
expect(foo).to.be.a('function')
})
})
to import the foo
file and run tests on it with Chai.
Conclusion
We should handle exceptions properly.
Also, we can use tests to prevent errors.
Pure functions and object parameters also help us write cleaner code.