Callback, Promise and Async/Await by Example in JavaScript
Tags: javascript, asyncawait, promises, callbacks
Published: 2021-05-20 20:05:38

---
title: Callback, Promise and Async/Await by Example in JavaScript
published: true
description: A practical, simple, code example based illustration of callback, promise, Async/Await syntax in JavaScript 
tags: JavaScript, AsyncAwait, Promises, Callbacks
canonical_url: https://www.geekabyte.io/2021/05/callback-promise-and-asyncawait-by.html
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3k6w2ci0n1zp8g99r5bi.png
---

This post is going to show, by way of code examples, how to take a callback based API, modify it to use Promises and then use the Async/Await syntax. This post won't go into a detailed explanation of callbacks, promises or the Async/Await syntax. For such a detailed explanation of these concepts please check [Asynchronous JavaScript](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous), which is a section of MDN Web Docs, that explains asynchronicity and how callbacks, promises, and the Async/Await syntax helps with working with asynchronous JavaScript.

This post is meant for the developer who has somewhat of an understanding of asynchronicity in JavaScript, but requires a straight to the point code example to serve as a quick syntax reference for how to take a callback based API, update it to use promises and finally use the Async/Await with it.

For demonstration purposes, we are going to use the [fs.readFile](https://nodejs.org/api/fs.html#fs_fs_readfile_path_options_callback), which is a callback based API from reading files. We will have a file `test.txt` that would contain some text, we will then have a file `script.js` that would open the file, read the contents, and print it to the terminal.

The code will first be implemented using callbacks, it would then be updated to use Promises, and finally, instead of using Promise directly, it will be updated to use Async/Await.

Let's get started.

### Using Callbacks

We first create a directory where we are going to work from, create also the file that will contain our code, and the two files that we would be reading from.

We first create the two files with contents.

```bash
$ mkdir ~/code
$ touch ~/code/script.js
$ echo "Beam me up, Scotty" > ~/code/test.txt
$ cd ~/code/
```

Next in the `script.js` file, we have the following code:

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

function readFileCallBack() {

fs.readFile("./test.txt", 'utf8',  (err, data) => {
  if (err) {
     console.error(err)
     return
   }
   console.log(data.trim() + " [callback]")
  })

}

readFileCallBack()
```

Executing the script by running node `script.js` should get "Beam me up, Scotty" printed to the terminal:

```bash
$ node script.js
Beam me up, Scotty [callback]
```

### Using Promises

Update `script.js` and add a version of `readFileCallback` that uses promises. It looks like this:

```javascript

function readFilePromise() {
  return new Promise((resolve, reject) => {
     fs.readFile("./test.txt", 'utf8',  (err, data) => {
     if (err) {
       reject(err)
       return
     }

      resolve(data.trim())
    })
  });
}

readFilePromise()
 .then(data => console.log(data  + " [promise]"))
 .catch(err => console.log(err))
```

Execute the script by running node `script.js`:

```bash
$ node script.js
Beam me up, Scotty [callback]
Beam me up, Scotty [promise]
```

### Using Async/Await

Update `script.js` and add a third version that uses the Async/Await syntax. Since Async/Await is a syntax that makes using promises easier, the Async/Await implementation would make use of the `readFilePromise()` function. It looks like this:

```javascript
async function readFileAsync() {
  try {
    const data = await readFilePromise()
    console.log(data.trim() + " [async-await]")
  } catch (err) {
    console.log(err)
  }
}

readFileAsync()
```

Executing the script by running node `script.js` will print something similar to this, to the terminal:

```bash
Beam me up, Scotty [callback]
Beam me up, Scotty [promise]
Beam me up, Scotty [async-await]
```

The complete file with the 3 implementations is presented below:

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

// callback
function readFileCallBack() {

fs.readFile("./test.txt", 'utf8',  (err, data) => {
  if (err) {
    console.error(err)
    return
  }
  console.log(data.trim() + " [callback]")
  
 })

}

readFileCallBack()

// promise
function readFilePromise() {
  return new Promise((resolve, reject) => {
     fs.readFile("./test.txt", 'utf8',  (err, data) => {
     if (err) {
       reject(err)
       return
     }

      resolve(data.trim())
    })
  });
}


readFilePromise()
 .then(data => console.log(data  + " [promise]"))
 .catch(err => console.log(err))


// async/await
async function readFileAsync() {
  try {
    const data = await readFilePromise()
    console.log(data.trim() + " [async-await]")
  } catch (err) {
    console.log(err)
  }
}

readFileAsync()
```

### Error Handling

To illustrate that the error handling in the 3 implementation work as expected, rename the `test.txt` file and rerun the script:

```bash
$ mv test.txt test.txt.backup
$ node script.js
[Error: ENOENT: no such file or directory, open './test.txt'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: './test.txt'
}
[Error: ENOENT: no such file or directory, open './test.txt'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: './test.txt'
}
[Error: ENOENT: no such file or directory, open './test.txt'] {
  errno: -2,
  code: 'ENOENT',
  syscall: 'open',
  path: './test.txt'
}
```

Showing that the error handling code, which is to just print the error to the console, works as expected in the 3 implementations.