Node.js - Asynchronous Flow
Tags: node, asynchronous, javascript, eventdriven
Published: 2020-11-30 23:17:46

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pgui77fph0kfc617ljvz.jpeg)

#### Overview
This article is **Part 2** of [Working With NodeJS](https://dev.to/meddy672/series/20844), a series of articles to help simplify learning Node.js. The topic which I will focus on here will be **Asynchronous Flow**.

#### Objectives
In this article we'll learn what asynchronous code is, and programming techniques to deal with asynchronous code. I'll also discuss the [Event Loop](https://nodejs.dev/learn/the-nodejs-event-loop) and how it plays a role in managing the application code.

#### Introduction
The Event Loop runs in a single thread which means that only one task can be executed at time. To alleviate code blocking issues, such as reading a large file, Node.js like JavaScript incorporated a Non Blocking I/O. This means the execution thread does not wait for the operation to complete before moving on to the next task.

#### Section 1 - Asynchronous Code
Asynchronous code is code that will execute at some point in the future. It can be thought of as code that must notify the Event Loop when it is done so it can be placed on the call stack and executed. Lets see an example.

##### asynchronous code example
```javascript
    setTimeout(() => {
        console.log('I\'m still executed last.');
    }, 0);

    console.log('I \'m executed first');
```
In the code snippet above, even though the `setTimeout` method delay is `0` the second console.log is executed first. This is because the `setTimeout` method is a piece of asynchronous code. When the Event Loop encounters the `setTimeout` method, it places it on the call stack, executes the `setTimeout` method, and immediately moves on to execute the next line of code. When the timer is finished, the Event Loop is notified and the callback function i.e 
```javascript
() => { 
   console.log('I\'m still executed last.');
 }
```
is placed at the end of the call stack. At this point the Event Loop has already moved forward to execute the second console.log. Lets look at an example that can be mistaken as asynchronous code.

##### mistaken as asynchronous code example
```javascript
let bar;
function asyncFunction(callback) {
    callback();
}

asyncFunction((cb) => {
    console.log('What is bar equal to?', bar);
});

bar = 1;
```
In the above code snippet, the `asyncFunction` is not really asynchronous. The `callback()` gets immediately invoked because it is synchronous. It in fact, goes line-by-line executing each line of code of the `asyncFunction`. Therefore  **`bar`** will be **undefined**.

#### Callbacks - Programing Technique 1
A callback in Node.js is one way of handling a piece asynchronous code. When the Event Loop encounters asynchronous code that takes a callback, the asynchronous code tells the Event Loop  *When I'm done I'll call you back*. At this point the callback is registered with the Event Loop. It is only when the callback completes the Event Loop is notified there is more code to run. Lets see an example.
##### readFile code snippet
```javascript
const { readFile } = require('fs');
readFile(__filename, (err, contents) => {
    if (err) {
        console.error(err);
        return;
    }
    console.log(contents.toString());
});
```
The `readFile` method out of the `fs` module takes a **filename** and a **callback** as parameters. Once all the file content is read, the callback will be made to the Event Loop. There are a few other things I would like to point as well.

1. You cannot do anything with the context of the `readFile` until the callback is completed. As developers, we tend to try to set some variable to some value in a callback and use it elsewhere within our code. This can be problematic as it could lead to **undefined** variables because nearly all Node.js API's are asynchronous.
2. If you define a **custom** callback function for your asynchronous operation, it is best practice that your first parameter be reserved for the error object. This is because all of Node.js callbacks follow the same protocol.

#### Promises - Programing Technique 2
A Promise is another way of handling a piece of asynchronous code. Promises provide away to avoid [Callback Hell](http://callbackhell.com/).  A Promise can be in one of [three states](https://github.com/domenic/promises-unwrapping/blob/master/docs/states-and-fates.md) - *Pending, Fulfilled, Rejected*. The initial state of a promise is pending until the resolve or reject methods are invoked. If you `resolve` a promise then its in the fulfilled state, and you can consume it using the chainable `.then(f)` function. If you `reject` a promise, or an error occurs, It is in the rejected state, and you can use the `.catch(f)` function to handle these scenarios. Lets see an example.

##### promise code snippet
```javascript

new Promise((resolve, reject) => {
    console.log('Initial');
    resolve('A');
})
.then((result) => {
    console.log(result);
})
.then(() => {
    throw new Error('Something failed');
    console.log('This will not execute');
})
.catch((err) => {
    console.error(err);
});
```

##### output
```
Initial
A
Error: Something failed
```

Lets look at a more practical example. I'll refactor the **readFile code snippet**  from the callback section earlier to return a promise that resolves to the content of a file.
##### refactored code from callback
```javascript
const { readFile } = require('fs');

function readFileProm() {
    return new Promise((resolve, reject) => {
        readFile(__filename, (err, content) => {
            if (err) reject(err)
            else resolve(content.toString())
        })
    })
}

const promise = readFileProm();

promise.then((content) => {
    console.log(content);
});

promise.catch((err) => {
    console.error(err);
});
```

The code snippet above will read its own file content to the console. In Node.js there is a helpful utility function called  [promisify](https://nodejs.org/dist/latest-v15.x/docs/api/util.html#util_util_promisify_original) out of the `util` module. Promisify takes asynchronous code that is callback based and converts it to promised based asynchronous code. Lets see an example. I'll refactor the code snippet above so that it uses the `promisify` function. The code will produce the same results.

##### promisify code snippet
```javascript

const { promisify } = require('util');
const { readFile } = require('fs');

const readFileProm = promisify(readFile);

const promise = readFileProm(__filename);

promise.then((contents) => {
  console.log(contents.toString());
})

promise.catch((err) => {
  console.error(err);
})
``` 

The code snippet above takes a piece of asynchronous code that is callback like `readFile`, and converts it to asynchronous code that is promise like `readFileProm`. With promise like asynchronous code we can begin using **async** and **await** to block progress within a function until a promise is resolved.

#### Async and Await - Programing Technique 3
As we learned earlier with asynchronous code, the execution thread will not wait for the function to finish before moving on to the next line of code. Therefore, the only way to obtain a value produced by a piece of asynchronous code is to have nested callbacks or chained then blocks. This is where *async* and *await* come into play. Async and await allow us to work with **promises** by suspending execution of further code until a promise is resolved. Once the promise resolves progress continues within the function. Lets see an example. I'll refactor the **promisify code snippet** from the promise section so it works with async and await.


##### async and await code snippet
```javascript
const { promisify } = require('util');
const { readFile } = require('fs');

const readFileProm = promisify(readFile);

async function read() {
    try {
        const content = await readFileProm(__filename);
        console.log(content.toString());
    } catch (err) {
        console.error(err);
    }
}

read().catch((err) => {
    console.error(err);
});
```
The code snippet above will produce the same result as the snippet before, but with a cleaner look to the code. In the code snippet above, I created a function `read` and made it `async` or asynchronous. This will allow the function to be **non blocking** and allow other code which is after it to be executed. Within the `read` function the `await` keyword is used on the promise like code. At this point, further execution of code is suspended until the promise is resolved.

If you like this post please leave rating and subscribe to the series. Take care.