Our blog

Why Use Asynchrony in Node.js: Avoiding Callbacks and Synchronous Functions

In Node.js, asynchrony is one of the main principles of code execution. This principle allows you to create highly efficient and fast applications. In this article, we will look at why callbacks are becoming bad practices and why you should not use synchronous functions in Node.js applications. Why callbacks have become a bad practice Callbacks […]

Category

Project Tips and Tricks

Posted

Serhii

May 16, 2024

In Node.js, asynchrony is one of the main principles of code execution. This principle allows you to create highly efficient and fast applications. In this article, we will look at why callbacks are becoming bad practices and why you should not use synchronous functions in Node.js applications.

Why callbacks have become a bad practice

Callbacks are callback functions in asynchronous operations that take typically 2 arguments. The first argument is an error or nothing, the second argument is the result of executing the function that called the callback if there are no errors.

  • Callback Hell.
    When an application gets bigger, old logics are filled with more functionality, the amount of code grows, so will the amount of nested synchronous code. The code can become hard to read, and from this follows an additional complexity on its support, because of the so-called “callback hell”.
  • Errors and flow control.
    Another significant disadvantage of callbacks is the difficulty of managing the flow of code execution and error handling.
  • Code support
    Since callbacks are usually a linked chain of calls, naming such a chain increases the probability of making a mistake when you have to embed or remove a link and have to keep in your head the contexts of several levels of nested functions. It is much easier to move, add or remove 1 promise call than to change related callback chains.
  • Debugging and testing
    Let’s imagine a situation where we need to write a migration for a relational database. In it you need to add five linked tables with external keys. If such logic is implemented on callbacks, it will require at least 5 nested functions, not taking into account wrappers for migration and additional abstractions. Such nested code will be more difficult to check and debug, which will affect the task execution time. 

Using this practice is definitely obsolete and has a number of negative factors. And if in some libraries you can meet implementations of functionality on callbacks, it is preferable to encapsulate such logic in abstraction and wrap it in promises.

Why you should not use synchronous functions:

Synchronous functions are functions that are executed synchronously, i.e. they block program execution until the current process is completed. An example is the “readFileSync” function from the “fs” library

  • Blocking the execution thread
    Since synchronous functions block the program execution flow, they impose certain performance limitations and responsibilities on the developer who uses them. This can lead to significant delays, especially in web applications.
  • Low performance
    If synchronous functions in code are far from rare, this approach can create a sluggish effect. The program will spend more time on executing its processes than necessary. This is especially noticeable in situations where you need to perform parallel processing of operations. In Node.js, which is originally built on an asynchronous execution model, the use of synchronous functions can lead to a critical slowdown of the application.
  • Scaling complexity
    Synchronous code is very likely to become a problem when scaling an application. Synchronous functions that block the execution thread are not an efficient use of server resources, especially in high-load systems.

Although there are places where a synchronous function may be appropriate, this is the exception rather than the rule. In most real tasks, the process logic will only slow down the process. For example, in the library “Sequelize” in the initialization file of models, according to the documentation or the template from “sequelize-cli“, we are advised to use “readdirSync“, we can easily get rid of the synchronous function by replacing it with a promises (“readFile“) from “fs.promises” or by creating a list of imported models.

Conclusion

Node.js already has enough tools to execute code correctly and efficiently, without using outdated or low-efficiency approaches.

At Swan Software Solutions, it’s common to work with tasks in a parallel manner, without using ploys and low-efficiency approaches. This helps to ensure high-quality and fast results that meet client requirements and industry standards. To find out more about how we could help your company with a custom solution, schedule a free assessment.