DeployU
Interviews / Backend Engineering / What is the difference between callbacks, promises, and async/await?

What is the difference between callbacks, promises, and async/await?

conceptual Asynchronous Programming Interactive Quiz Code Examples

The Scenario

You are a backend engineer at a fintech company. You are writing a new service that needs to make several asynchronous calls to other services to get the data it needs.

You are trying to decide whether to use callbacks, promises, or async/await to handle the asynchronous calls.

The Challenge

Explain the difference between callbacks, promises, and async/await. What are the pros and cons of each approach, and which one would you choose for this use case?

Wrong Approach

A junior engineer might only be familiar with one of these approaches. They might not be aware of the trade-offs between them, or they might not know how to choose the right one for a given use case.

Right Approach

A senior engineer would be able to provide a detailed explanation of the differences between callbacks, promises, and async/await. They would also be able to explain the trade-offs between each approach and would have a clear recommendation for which one to use in this use case.

Step 1: Understand the Evolution of Asynchronous Programming in Node.js

ApproachDescriptionProsCons
CallbacksA function that is passed as an argument to another function and is executed when the other function has completed.Simple and easy to understand for basic use cases.Can lead to “callback hell” (nested callbacks that are difficult to read and maintain).
PromisesAn object that represents the eventual completion (or failure) of an asynchronous operation.More readable and easier to chain than callbacks.Can be more verbose than async/await.
Async/awaitSyntactic sugar on top of promises that makes asynchronous code look and behave more like synchronous code.Very readable and easy to write.Can be more difficult to debug than promises if you are not careful.

Step 2: Choose the Right Tool for the Job

For our use case, async/await is the best choice. It is the most modern and readable way to write asynchronous code in Node.js, and it is well-suited for handling multiple asynchronous calls.

Step 3: Code Examples

Here are some code examples that show the difference between the three approaches:

Callbacks:

const fs = require('fs');

fs.readFile('file1.txt', 'utf8', (err, data1) => {
  if (err) throw err;
  fs.readFile('file2.txt', 'utf8', (err, data2) => {
    if (err) throw err;
    console.log(data1, data2);
  });
});

Promises:

const fs = require('fs').promises;

fs.readFile('file1.txt', 'utf8')
  .then(data1 => {
    return fs.readFile('file2.txt', 'utf8')
      .then(data2 => {
        console.log(data1, data2);
      });
  })
  .catch(err => {
    throw err;
  });

Async/await:

const fs = require('fs').promises;

async function readFiles() {
  try {
    const data1 = await fs.readFile('file1.txt', 'utf8');
    const data2 = await fs.readFile('file2.txt', 'utf8');
    console.log(data1, data2);
  } catch (err) {
    throw err;
  }
}

readFiles();

As you can see, async/await is the most readable and concise of the three approaches.

Practice Question

You need to make three asynchronous calls in a sequence, where each call depends on the result of the previous call. Which approach would be the most readable?