Correct way to write a non-blocking function in Node.js

Wrapping code in a promise (like you’ve done) does not make it non-blocking. The Promise executor function (the callback you pass to new Promise(fn) is called synchronously and will block which is why you see the delay in getting output.

In fact, there is no way to create your own plain Javascript code (like what you have) that is non-blocking except putting it into a child process, using a WorkerThread, using some third party library that creates new threads of Javascript or using the new experimental node.js APIs for threads. Regular node.js runs your Javascript as blocking and single threaded, whether it’s wrapped in a promise or not.

You can use things like setTimeout() to change “when” your code runs, but whenever it runs, it will still be blocking (once it starts executing nothing else can run until it’s done). Asynchronous operations in the node.js library all use some form of underlying native code that allows them to be asynchronous (or they just use other node.js asynchronous APIs that themselves use native code implementations).

But the program waits before printing second and third lines. Can you explain what should be the proper way to get “before” and “after” printed first and then (after some time) the result?

As I said above, wrapping things in promise executor function doesn’t make them asynchronous. If you want to “shift” the timing of when things run (thought they are still synchronous), you can use a setTimeout(), but that’s not really making anything non-blocking, it just makes it run later (still blocking when it runs).

So, you could do this:

function longRunningFunc(val, mod) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            sum = 0;
            for (var i = 0; i < 100000; i++) {
                for (var j = 0; j < val; j++) {
                    sum += i + j % mod
                }
            }
            resolve(sum)
        }, 10);
    })
}

That would reschedule the time consuming for loop to run later and might “appear” to be non-blocking, but it actually still blocks – it just runs later. To make it truly non-blocking, you’d have to use one of the techniques mentioned earlier to get it out of the main Javascript thread.

Ways to create actual non-blocking code in node.js:

  1. Run it in a separate child process and get an asynchronous notification when it’s done.
  2. Use the new experimental Worker Threads in node.js v11
  3. Write your own native code add-on to node.js and use libuv threads or OS level threads in your implementation (or other OS level asynchronous tools).
  4. Build on top of previously existing asynchronous APIs and have none of your own code that takes very long in the main thread.

Leave a Comment