The Most Important Thing You Don't Know About Promises

The Most Important Thing You Don't Know About Promises

Β·

3 min read

Take a look at the below code:

const promise = new Promise((resolve, reject) => {
  resolve();
});

promise
  .then(() => {
    console.log('first');
  })
  .then(() => {
    console.log('second');
  })
  .then(() => {
    console.log('third');
  })
  .catch((error) => {
    console.log('error', error);
  });

If you execute the above code, you'll see the following output:

promise_output.png

As you know each .then handler will be executed one after the another and the value returned from the previous .then handler is passed to the next .then handler so we get the output of the above code as:

first
second
third

which is as expected.

But now, take a look at the below code:

const promise = new Promise((resolve, reject) => {
  resolve();
});

promise
  .then(() => {
    console.log('first');
  })
  .then(() => {
    setTimeout(() => {
      console.log('second');
    }, 2000);
  })
  .then(() => {
    setTimeout(() => {
      console.log('third');
    }, 1000);
  });

If you execute the above code you will see the following output:

waiting_promises.gif

We're getting the output as:

first
third
second

In the above code, the second .then handler has a setTimeout function call with 2000 milliseconds(2 seconds) as the timeout so it will not be executed immediately, but the third .then will be executed before the second .then handler as it has a 1000 millisecond(1 second) timeout.

Therefore, we're seeing first printed immediately and after 1 second, third will be printed and after 2 seconds second will be printed.

So If any .then handler is making an API call or doing some long-running operation then the next .then handler function might be executed immediately even If the long-running operation in the previous .then handler is not completed yet.

When you attach multiple .then handlers, it’s not guaranteed that the next .then handler will be called only after the previous .then handler finishes if there is additional asynchronous code inside the handler.

There is a way to fix this default behavior.

We can return a new promise from the second .then handler and only call resolve or reject once we are done with our API call or any other long-running operation.

This will guarantee that the next .then will always be executed after the previous one has finished.

This is because when we call a promise, the Promise will wait until we explicitly call resolve or reject inside the promise.

The following is the code that will maintain the order sequence:

const promise = new Promise((resolve, reject) => {
  resolve();
});

promise
  .then(() => {
    console.log('first');
  })
  .then(() => {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        console.log('second');
        resolve();
      }, 2000);
    });
  })
  .then(() => {
    setTimeout(() => {
      console.log('third');
    }, 1000);
  });

As you can see, we're returning a promise from the second .then handler so the next .then handler will be executed only if the second .then handler resolves.

If you execute the above code you will see the following output:

promise_fix.gif

As you can see now, each .then handle is executed only after the previous one is finished executed.

That's it about this article.

Thanks for reading!

Check out my recently published Mastering Redux course.

In this course, you will learn:

  • Basic and advanced Redux
  • How to manage the complex state of array and objects
  • How to use multiple reducers to manage complex redux state
  • How to debug Redux application
  • How to use Redux in React using react-redux library to make your app reactive.
  • How to use redux-thunk library to handle async API calls and much more

and then finally we'll build a complete food ordering app from scratch with stripe integration for accepting payments and deploy it to the production.

Want to stay up to date with regular content regarding JavaScript, React, Node.js? Follow me on LinkedIn.

Did you find this article valuable?

Support Yogesh Chavan by becoming a sponsor. Any amount is appreciated!