Oct 29, 2020



min read

Oct 29, 2020



min read

An introduction to Promises and Async Programming

At some point in development you may find yourself using a callback. There’s nothing wrong with that, but then you realise you need another callback to fire after the first callback, and so on. This is referred to as ‘Callback Hell!’

Codehouse Dev Team



person checking a mobile tablet
person checking a mobile tablet
person checking a mobile tablet

Callbacks are a convention of JavaScript and are the same as any other function. The difference is not what's inside them, but when they’re used.

Callbacks are typically used after a task that takes time to complete. JavaScript is generally synchronous. It will complete one task before moving onto the next, but developers aren't keen on waiting for tasks with unknown completion times.

What happens if the task doesn’t even finish and throws an error half way through the process? This is where the use of Promises and Asynchronous programming come in.


The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value. A Promise is used to overcome issues with multiple callbacks and provides a better way to manage success and error conditions.

A Promise object has 3 states:

  • Pending: The async operation is going on

  • Resolved: The async operation is completed successfully

  • Rejected: The async operation is completed with error

Usually the Promise would wrap around an AJAX call or any other asynchronous code. But for this example the Math.random() is used to test both resolved and rejected results.

There's no need to write in an else block because the Promise stops as soon as the first condition is returned to the object.

Developers can chain Promises using .then() and .catch(). The .then() method accepts two callbacks. The first callback is invoked when the Promise is resolved. The second callback is executed when the Promise is rejected.

As a way of error handling the .catch() method can be used. It returns a Promise object and deals with rejected results only.

If there’s a scenario where the fastest result is needed, regardless of whether the Promise is resolved or rejected, use the .race() method. The .race() method uses an iterable as its parameter such as an array.

If there are multiple Promises the .all() method can be used for them to finish. This method takes an array.

Async and await

Think of async and await as syntactic sugar wrapped around Promises to make them easier to work with. Below is an example of chaining Promises:

The first invocation of checkLanguage chains resolves and allows the chain to continue. The second invocation of checkLanguagepromise gets rejected and the error is caught and outputed in the console. It’s possible to keep chaining by using .then() but this would end up being untidy.

Instead, the chaining can be re-written:


  • Using async and await is easier to reason with

  • It looks like synchronous code so it’s more readable and understandable

  • Async await makes it easier to write and work with promises

  • Await ensures it returns the result of the promise being executed

  • Promises and async/await accomplish the same thing. They make retrieving and handling asynchronous data easier. They eliminate the need for callbacks, simplify error handling, reduce extraneous code, make waiting for multiple concurrent calls to return and adding additional code in between calls easier

Find out more about faster async functions and Promises.

Working with Codehouse

Our front-end development team are constantly looking at ways to improve the development process the user experience. We work on exciting design and build projects often on CMS like Sitecore. Get in touch to find out more.

Sign up for insights, news and more...

Join the product and digital innovators at the frontline of digital transformations who benefit from our newsletter