As part of our current series on Node.js and as a follow-on from Five Enterprise Apps Using Node.js Under the Hood, in this post, we look at three major traps when building enterprise Node.js apps and workarounds for how to avoid them.
As we’ve seen, many enterprise-level organizations - from NASA to Netflix - are using Node.js to build their applications. While there are many advantages to using Node.js, there are some pitfalls that developers can fall foul of while developing their applications. Let’s take a look at three major ones and some of their workarounds.
1. Bugs introduced by dynamic typing
In programming languages, type systems are rules used to manage data in variables, expressions, and functions.
Dynamically typed languages check the type of the data when the program is running. Statically typed languages check data types when the program is being compiled. Dynamically typed languages have several advantages over statically typed languages, such as:
- They are more concise: shorter code is quicker to write, read and maintain;
- There are more possibilities for interactivity: dynamic typing is a good fit for interactive, REP-esque programming for rapid prototyping, real-time debugging of running program instances and live coding;
That said, dynamically typed languages can easily introduce bugs due to a lack of type checking.
How to avoid this?
- It lets you describe the shape of an object, providing superior documentation and the opportunity to have TypeScript validate that your code will run correctly before you run it.
- As well as preventing bugs, TypeScript can improve the code editing process when used with a code editor with TypeScript integration.
2. Challenges with callbacks
Some easy mistakes to make when using callbacks include:
Invoking a callback more than once.
How to avoid it: One way is to add a return keyword before every callback invocation.
Deeply nesting callbacks
Keeping a number of queued tasks in the background, each with its own callback, is known as “callback hell” and can lead to the code becoming difficult to understand and laborious to maintain.
How to avoid it:
- Use a utility Node.js package, such as Async.js, that handles asynchronous JS patterns.
- Declare these tasks as small functions and link them together.
Expecting callbacks to run synchronously
How to avoid it: Anything that needs to take place after a callback has fired should be invoked from within it.
Most of the issues that spring from nested callback functions can be overcome with the use of promises in Node.js. A promise is an enhancement to callback functions in Node.js. A promise can help alleviate the problems associated with nesting multiple callback functions together. The essential concept of a promise is the return value. Promises can be nested within one another to improve the look of code and make it easier to maintain, particularly when one asynchronous function is called after another.
3. Performance bottlenecks due to overuse of CPU-bound tasks
The biggest challenge developers face with Node.js is its inability to quickly process CPU bound tasks. When Node.js receives a CPU bound task, it sets all the CPU available to process it first, then answer other queued requests. This leads to slow processing and a delay in the event loop. As Node.js processes tasks asynchronously, it executes JS code on its single thread on an event basis, which can lead to an event loop.
How to avoid it?
Updates to Node.js have improved this issue in the last few years. In 2018, multithreading was introduced as an experimental feature with the 10.5.0 update. A new module called Worker threads enables the use of threads that execute JS in parallel. They are intended to help with performance of CPU-intensive JS operations. However, note that Worker threads can only be performed on machines with multiple cores since Node.js allows you to use one core per thread. Heavy parallel processes can be run on a different thread; however, this feature is still experimental in Node.js v12 (now on v14).
While Node.js is a relatively easy runtime for newcomers to get started on, there are some surprising gotchas. Fortunately, as we have seen, there are workarounds for the major traps and pitfalls.