Concurrency in JavaScript.

Learn how to write asynchronous non-blocking code in JS.

Onejohi
5 min readDec 21, 2018

Concurrency. What is it?

Concurrency means multiple computations are happening at the same time. Concurrency is everywhere in modern programming, whether we like it or not: Multiple computers in a network. Multiple applications running on one computer. Multiple processors in a computer (today, often multiple processor cores on a single chip — MIT

As you should know by now, JavaScript runs on a single thread. This thread is event-based and responds to events when they occur. So how does it not block other functions from executing? Well, the answer is simple, it does. JS functions are hoisted, as pointed out by my friend Featherweight, functions declared in variables will not execute if called before being defined as the variable doesn’t exist, while normal functions do execute anyways as they’re hoisted.

sayHi()
function sayHi() {
console.log("Hello")
}
//this will worksayHello()
let sayHello = () => {
console.log("hello")
}
//this will not work

So, this means JavaScript code is parsed sequentially. Which is the direct opposite of what we’re trying to achieve. Fortunately, JavaScript comes with three features that allow you to run code in concurrently. Callbacks, Promises and Async/Await.

Callbacks.

NodeJS is built for quick i/o operations. It makes heavy use of callbacks which come built in. Callbacks are asynchronous functions that call back after their execution completes. So in essence, the main thread receives an event which then makes it fire the handler function for the specific event. The handler for the event delegates a task and start’s processing it while the main thread returns to listen for more events immediately. If another request comes in, the main thread will be able to intercept it even while the handler is still running its long process and the main thread will fire another handler function to execute while it listens for more events. This makes NodeJS callback functions non-blocking and allows for asynchronous (concurrent) operations.

Let’s run add some code after the function to see if the code will wait for callbackFunc to complete or will continue while the callback is pending. At the bottom add, console.log("This should appear before the array").

Promises.

A promise is an object that represents the eventual completion or failure of an asynchronous operation like requesting data using the fetch() api. Here’s a simple example of a promise.

As you can see from line 15, a promise is merely a proxy for an unknown value when the promise is created. This allows you to create statements that handle the eventual success value or failure reason of the promise. This lets asynchronous methods return values similar to synchronous methods that we can work with before the promise is returned at some point in future.

A promise has three states.

  1. Pending (pending): initial state, neither fulfilled nor rejected. More of currently running at the moment.
  2. Fulfilled (fulfilled): When the operation completes successfully.
  3. Rejected (rejected): When the operation fails.

A pending promise can either be fulfilled with a value or rejected with an error where the associated handlers queued up by a promise’s then method are called. The catch method can be used to call the handler when the promise is rejected where you can get the reason of failure.

Async functions. (Async/Await)

The async function() defines an asynchronous function that returns an AsyncFunction object. This function operates asynchronously via the event loop using an implicit Promise to return a value. The only difference is that the syntax of async functions is more similar to synchronous functions than promises, so if you’re more accustomed to synchronous code, async functions are the way to go for you.

An async function can contain await expression that pauses the execution of the async function and awaits for the passed promise resolution or rejection. It then resumes the async method and returns a resolved value.

Note: The await keyword is only valid inside async functions, a SyntaxError will be raised if used outside async functions.

Copy and run this code on your terminal to observe how the functions are executed. I made the labels to log out what they represent, sequential functions and parallel functions. You should get something similar to this.

As you can see, you can see how each statement is executed either sequentially or concurrently.

Conclusion.

Concurrent code is much better than sequential as it’s non-blocking and can handle multiple users or events at the same time without any problem. However, it is important to remember that JavaScript is only a viable option when fast input and output of data is required (gaming, social networking, video streaming, instant messaging) and not recommended when it comes to heavy computing tasks. I would recommend Go for CPU intensive applications instead.

A lot of problems arise when using sequential code, in today's world, everything is connected to the internet. This means your application might have to make some API calls every now and then. It’s difficult to know how long it will take for the data to be processed and retrieved, you wouldn’t want your application to hang while it’s loading your user’s feed, would you? The event loop in NodeJS sort of runs your script over and over every time an event is detected. Since JS is single threaded, it offloads it’s operations mostly as callbacks in NodeJS thereby ensuring executions don’t block each other while they are running. When a NodeJS app starts, the event loop is initialized, processes the script then begins processing the event loop.

Although NodeJS is designed with an asynchronous event model where it’s APIs make use of callbacks, the fact that it is single-threaded means it can only run a single process with a single thread on a single core. This makes it highly unsuitable for CPU intensive tasks as only I/O operations are executed in parallel. However, with that said, you can make use of multiple cores and processes in NodeJS using a load balancer that would distribute your events across all your NodeJS processes just in case you already have a production app in NodeJS that does some CPU intensive tasks and don’t have time to rewrite in Go or Python.

A million thanks to checking out my article, leave a few claps and share to help your peers if you feel you have learned something. 😉

--

--

Onejohi

Creative 🚀 | Gamer 🎮 | Web & App developer 💻📱 | Graphics Designer 📏📝 | Entrepreneur 💶 | Cool AF 😎🤓 https://onejohi.com | WhatsApp +254727321766