Node.js has given cutting-edge web applications with two way, real-time connections where both server and client could communicate with each other. Regardless of how difficult Node.js makes writing safe code, and how easy it makes writing highly concurrent code, the platform has been around for quite a while and has been used to build number of robust and sophisticated web services. These web services scale well and have proven their stability through their stability through their endurance of time on the internet.
But just like any other platform, Node.js is vulnerable to developer issues. Some of these mistake lowers the performance, while others make Node.js appear straight out unusable for what you are trying to achieve. Here we’ll discuss most common mistakes that Node.js developers make, and how it can be avoided.
Know the features of latest version Node.js 17 at- What’s New In Node.js 17?
Most Common Mistakes To Avoid In Node.js Development-

1. Event Loop Blocking-
Being a single-threaded environment, no two parts of apps can run in parallel. Simply, since Node.js runs on single-thread, anything that blocks event look, blocks everything. Concurrency is achieved by handling input-output operations asynchronously. For instance, What allows Node.js to focus on other parts of app is a request to database engine, from Node.js to fetch some documents.
// Trying to fetch an user object from the database. Node.js is free to run other parts of the code from the moment this function is invoked..
db.User.get(userId, function(err, user) {
// .. until the moment the user object has been retrieved here
})
But a part of CPU-bound code in Node.js instance with thousands of clients connected is all it takes to block the event loop, that makes all the clients wait. CPU- bound codes include attempting to sort a large array, running a long loop, and so on. For instance:
function sortUsersByAge(users) {
users.sort(function(a, b) {
return a.age < b.age ? -1 : 1
})
}
Calling this “SortUsersByAge” function may be fine if run on a small “users” array, but with a large array, it will have a horrible impact on performance. If this must be done and you’re certain that there will be nothing waiting on the event loop(for instance, if this was part of command line tool that you’re building with Node.js and it wouldn’t matter if entire thing ran synchronously), then this may not be an issue.
But in Node.js server instance trying to serve thousands of users simultaneously, such a pattern can prove fatal.
If users array was retrieved from the database, the best solution will be- to fetch it already sorted directly from the database. If event loop blocked by loop written to compute the financial transaction data, it could be deferred to some external worker/queue setup to avoid hogging the event loop.
There’s no perfect solution for this type of Node.js problem, instead every case needs to be addressed individually. Main idea is to not do CPU intensive work within front-facing Node.js instances- the ones client connect to concurrently.
2. Deeply Nesting Callbacks-
Generally, nested callbacks referred to as “callback hell”, is not a Node.js issue in itself. But this can cause problems making code quickly spin out of control:
function handleLogin(..., done) {
db.User.get(..., function(..., user) {
if(!user) {
return done(null, ‘failed to log in’)
}
utils.verifyPassword(..., function(..., okay) {
if(okay) {
return done(null, ‘failed to log in’)
}
session.login(..., function() {
done(null, ‘logged in’)
})
})
})
}
In this way, by nesting callbacks, you can easily end up with error-prone, hard to read and also maintain code.
One solution is to declare these task as small functions and then link them. Though the clean solution is to use utility Node.js package that manages asynchronous Javascript patterns like Aync.js:
function handleLogin(done) {
async.waterfall([
function(done) {
db.User.get(..., done)
},
function(user, done) {
if(!user) {
return done(null, ‘failed to log in’)
}
utils.verifyPassword(..., function(..., okay) {
done(null, user, okay)
})
},
function(user, okay, done) {
if(okay) {
return done(null, ‘failed to log in’)
}
session.login(..., function() {
done(null, ‘logged in’)
})
}
], function() {
// ...
})
}
Just like “async.waterfall”, there are lost of functions that Async.js provides manage with different asynchronous patterns.
3. Invoking Callbacks, Multiple Times-
Javascript is popular because of relying on callbacks. Callbacks were the only way asynchronous elements of your code communicated with each other in Node.js until promises came into picture. Still package developers design their APIs around callbacks and hence callbacks are in use. Mistake that developers make while using callbacks is calling them multiple times.
No comments:
Post a Comment