A journey to Asynchronous Programming: NodeJS FS.Promises API

This post is about how Node.Js performs tasks, how and why one would use async methods and why and when one should use sync methods. We will also see how to make use of the new FS. Promises API.

Throughout this post, we will look at the many ways to write code the asynchronous way in Javascript and also look at:

✅ How asynchronous code fits in the event loop
✅ When you should resort to synchronous methods
✅ How to promisify FS methods and the FS.Promises API


To make the best use of this post, one must already be:

✅ Sufficiently experienced in Javascript and NodeJS fundamentals (Variables, Functions, etc.)
✅ Had some level of exposure to the FileSystem module (Optional)

Refer to the resources section if you wish to satisfy the prerequisites and gain the best use of this post


Once you're done reading this post you will feel confident about asynchronous programming and will have learned something new but also know:

  • What an event loop and the call stack is and how it fits with async programming

  • About synchronous methods and when to use them

  • About callback hell, the demerits of using callback methods in fs

  • That there are other libraries out there like bluebird that solved this issue, but now there's native support for fs modules with async/await, and their version numbers

  • To use the fs. promise API next time to avoid callback hell

⭐- If you hang tight there's also some bonus content regarding some best practices when using certain FileSystem methods!

The Event Loop and the Call Stack: How does asynchronous flow work

Javascript achieves concurrency through what is known as an event loop. This event loop is what is responsible for executing the code you write, processing any event that fires, etc. This event loop is what makes it possible for Javascript to run on a single thread and handle asynchronous tasks, this just means that Javascript does one thing at a time.

This might sound like a limitation but it is definitely something that helps. It allows you to work without worrying about concurrency issues and surprisingly the event loop is non-blocking! Of course, unless you as a developer purposely do something to block it.

The event loop looks more or less like this:

This loop runs as long as your program runs and hence called the event loop.

To better understand asynchronous programming though, one must understand the following concepts:

  • Call Stack: The call stack is where all your code gets pushed into and then executed one by one. Each function pushed into the call stack is called a "frame". These frames stack up on top of each other, and the last one that was pushed gets executed the first.

  • Heap: All objects/non-primitives are allocated in the heap. This is a large amount of memory that mostly does not have any proper structure.

  • Callback Queue: This is where the asynchronous code gets thrown into, and waits till their time for execution comes.

  • Job Queue: A recently introduced type of queue reserved primarily for Promises. All thenables from your Promise code, are pushed into this queue.

Let's take a look at the following code example and see how a typical execution flow looks like: