How to Write Asynchronous JavaScript Code
Tags: codenewbie, javascript, node
Published: 2021-05-29 22:37:18

# How to Write Asynchronous Code in NodeJS

JavaScript is a non-blocking, single-threaded programming language. It will not go from top to bottom, running your functions one line at a time like you would expect.

For example, here is some simple code to read a file:

```javascript
const fs = require("fs");

console.log("starting");
fs.readFile("/path/to/helloworld.txt", "utf8", (err, data) => {
  if (err) console.log(err);
  console.log(data);
});
console.log("finishing");
```

You may expect the result to be 

```bash
starting
<file contents>
finishing
```

But instead you get:
```bash
starting
finishing
<file contents>
```

This is because JavaScript does not stop. It will keep going down your code while waiting for a process to finish. There are three ways to handle this and I'll go over them from worst to best.

## The Humble Callback

To use callbacks for this code, you would do the following:

```javascript
console.log("starting");
fs.readFile("/path/to/helloworld.txt", "utf8", (err, data) => {
  if (err) {
    console.log(err);
    return; //or throw(err) or something else to strop the function
  } else {
    console.log(data);
    console.log("finishing");
  }
});

```

**Note: be sure to add a return after an error message and to use if/else to make sure the function does not continue if there is a problem.

## Promises

You have to keep nesting callback functions within callback functions which can lead to deeply-nested code that is hard to read, better known as callback hell.

Promises are wonderful additions to JavaScript to rescue JavaScript developers from callback hell.

You can read more about Promises in depth and how to create them on [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), but here is an example of how to consume them. Most APIs will have some way to use their code as a promise whether it is NodeJS's `util.promisify` or AWS's `.promise()` method for most of their API. For this example, we'll use promisify:

```javascript
const fs = require("fs");
const { promisify } = require("util");
const ReadFilePromise = promisify(fs.readFile);

console.log("starting");
ReadFilePromise("/path/to/helloworld.txt", "utf8")
  .then((data) => console.log(data))
  .catch((err) => console.log(err))
  .finally(() => console.log("finishing"));
```

You add a `.then()` for the data, a `.catch()` for the error, and a `.finally()` for anything you want to do after the data or error is returned.

## Async/Await

Finally we'll come to my favorite way to write JavaScript code, async/await. The `async` keyword is syntactic sugar that allows a function to return a `Promise`. So for this example we can use the same `ReadFilePromise` from the last example. We'll need to wrap this logic inside an `async` function and call it:

```javascript
const ReadFileAsync = async(path) => {
  console.log("starting");
  try {
    let data = await ReadFilePromise(path)
    console.log(data)
  } catch (error) {
    console.log(error)
  }
  console.log("finishing")
}

ReadFileAsync("/path/to/helloworld.txt", "utf8")
```

**NOTE: adding async to a function using callbacks does not make it work asynchronously. The function will still be using callback, but JavaScript now thinks it will return a Promise.**

You want to wrap your `await` inside a `try/catch` to allow for error handling. Speaking of error handling...

## How To Do Error Handling

To make sure your function bubbles the error up to the code using your function, `throw` it!

Let's my `ReadFileAsync` a function that another function can use.

```javascript
const ReadFileAsync = async (path) => {
  console.log("starting");
  try {
    return await ReadFilePromise(path);
  } catch (error) {
    throw error;
  }
};

async function main() {
  try {
    let data = await ReadFileAsync("/path/to/helloworld.txt", "utf8");
    console.log(data);
  } catch (error) {
    console.log(error);
  } finally {
    console.log("finishing");
  }
}

main()
```