JavaScript Interview Questions: Promises
Tags: javascript, webdev, programming, beginners
Published: 2021-01-24 01:55:13

**Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62**

**Subscribe to my email list now at http://jauyeung.net/subscribe/**


To get a job as a front end developer, we need to nail the coding interview.

Promises are important parts of JavaScript because of the pervasive use of asynchronous programming.

In this article, we’ll look at some common questions about JavaScript promises.

### What are Promises?

Promises are one way to handle asynchronous operations in JavaScript. Each promise represents a single operation.

It’s made to solve the problem of combining multiple pieces of asynchronous code in a clean way.

With promises, we can avoid nesting callbacks too deeply.

For example, instead of writing deeply nested callbacks as follows:

```
const fs = require('fs');

fs.readFile('somefile.txt', function (e, data) {

  fs.readdir('directory', function (e, files) {

    fs.mkdir('directory', function (e) {

    })
  })
})
```

We write:

```
const fs = require('fs');

const promiseReadFile = (fileName) => {
  return new Promise((resolve) => {
    fs.readFile('somefile.txt', function(e, data) {
      resolve(data);
    })
  })
}

const promiseReadDir = (directory) => {
  return new Promise((resolve) => {
    fs.readdir(directory, function(e, data) {
      resolve(data);
    })
  })
}

const promiseMakwDir = (directory) => {
  return new Promise((resolve) => {
    fs.mkdir(directory, function(e, data) {
      resolve(data);
    })
  })
}

promiseReadFile('somefile.txt')
.then((data)=>{
  console.log(data);
  return promiseReadDir('directory')
})
.then((data)=>{
  console.log(data);
  return promiseMakwDir('directory')
})
.then((data)=>{
  console.log(data);
})
```

We chained promises instead of nesting them as follows:

```
promiseReadFile('somefile.txt')
.then((data)=>{
  console.log(data);
  return promiseReadDir('directory')
})
.then((data)=>{
  console.log(data);
  return promiseMakwDir('directory')
})
.then((data)=>{
  console.log(data);
})
```

This is why we want to write promises for long chains of promises instead of deeply nested callbacks. It’s much easier to read.

Promises have 3 states. They can be pending, which means the outcome isn’t known yet since the operation hasn’t start yet.

It can be fulfilled, which means that the asynchronous operation is successful and we have the result.

It can also be rejected, which means that it failed and has a reason for why it failed.

A promise can be settled, which means that it’s either fulfilled or rejected.

Also, in the code above, we called the `resolve` function to return the value of the promise. To get the resolved value of the promise, we get the resolved value from the parameter of the callback.

`data` in each callback has the data that’s resolved from the promise above it.

To run the next promise in the callback, we returned the next promise.

To reject a promise, we call the `reject` function in the callback that we pass into the `Promise` constructor.

For example, we can change the code above to the following:

```
const fs = require('fs');

const promiseReadFile = (fileName) => {
  return new Promise((resolve, reject) => {
    fs.readFile('somefile.txt', function(e, data) {
      if (e){
        reject(e);
      }
      resolve(data);
    })
  })
}

const promiseReadDir = (directory) => {
  return new Promise((resolve, reject) => {
    fs.readdir(directory, function(e, data) {
      if (e){
        reject(e);
      }
      resolve(data);
    })
  })
}

const promiseMakwDir = (directory) => {
  return new Promise((resolve, reject) => {
    fs.mkdir(directory, function(e, data) {
      if (e){
        reject(e);
      }
      resolve(data);
    })
  })
}

promiseReadFile('somefile.txt')
.then((data)=>{
  console.log(data);
  return promiseReadDir('directory')
})
.then((data)=>{
  console.log(data);
  return promiseMakwDir('directory')
})
.then((data)=>{
  console.log(data);
})
.catch((err)=>{
  console.log(err);
})
```

Once a promise rejected, the ones that come after it won’t run.

We can get the error details and do something with it in the `catch` function’s callback like we have above.

In the code above, we converted each asynchronous code into a promise by creating a function and then returning a promise in it that calls `resolve` to fulfill the promise and `reject` to reject the promise with an error value.

### What is async/await?

`async/await` is a new way to write promise chains in a shorter way.

For example, instead of calling the `then` function with a callback like we had above, we rewrite it to:

```
try {
    const readFileData = await promiseReadFile('somefile.txt');
    console.log(readFileData);
    const readDirData = await promiseReadDir('directory');
    console.log(readDirData);
    const makeFileData = await promiseMakwDir('directory');
    console.log(makeFileData);
    return makeFileData;
  }
  catch(err){
    console.log(err);
  }
})();
```

This is the same as:

```
promiseReadFile('somefile.txt')
.then((data)=>{
  console.log(data);
  return promiseReadDir('directory')
})
.then((data)=>{
  console.log(data);
  return promiseMakwDir('directory')
})
.then((data)=>{
  console.log(data);
})
.catch((err)=>{
  console.log(err);
})
```

As we can see, `async/await` is much shorter than writing `then` with callbacks.

We don’t have callbacks and we don’t have to return promises in each callback.

`readFileData`, `readDirData`, and `makeFileData` are the same as the `data` parameter in each `then` callback.

`try...catch` in the `async` function is the same as the `catch` call and callback at the end. `err` has the same error object in both examples.

`async` functions can only return promises, so `makeFileData` is actually the resolved value of a promise, not the actual value.

Even though it looks like a synchronous function, it doesn’t behave the same.

### Conclusion

Promises are a way to chain asynchronous operations cleanly without deeply nested callbacks.

We can make them even shorter and cleaner with the `async/await` syntax.