two people riding a bike, holding hands making promises
Web Development |

Async adventures or: How I learned to stop worrying and love promises

Jessica Schneck

April 9, 2019

Let’s talk about Promises and async/await in JavaScript. Before I started learning what Promises and async/await were all about, I had to learn callbacks first. That did not turn out to be quite as much fun as I’d hoped, especially the deeper I descended into my own personal callback hell. Luckily everyone told me not to worry, I would learn a more comfortable solution in the next step and inwardly, the song „I’m so excited“ by the Pointer Sisters started sounding in my head. (A song I can very much recommend!)

Do you want to load external content from https://media.giphy.com/media/3ohzdIuqJoo8QdKlnW/giphy.gif ?

Promises — My personal holy grail

People tried to explain them to me with hands and feet but for me as a rookie JavaScript Promises were confusing and difficult to understand. Honestly, I didn’t really get the advantages compared to callbacks at first but my willingness to learn was too great to stop me. So I worked through lots of excercises about Promises and with every new Promise I wrote and used I understood even more. At some point I thought: „Hmm, maybe not that bad.“ My enthusiasm raised and after a while everything was (almost) clear to me.

A promise could have three states: pending, rejected or resolved.

  • Pending means that the Promise is still in the making
  • If a Promise is resolved it returns a Promise object that is resolved with a given value or promise passed as value
  • A rejected Promise returns the reason why the Promise was rejected
function somePromise() {
	return new Promise((resolve, reject) => {
		if(someCondition) {
			resolve(„Yay!“)
		} else {
			reject(new Error(„Oh no!“))
		}
	})
}

Yes, from that point on „Team Promises“ had totally won me over! I resolved and rejected like a champion and chained everything I could find. Nothing was safe from me. Nothing could stop me.

Do you want to load external content from https://media.giphy.com/media/l0HlTPnnfzRsf4f2U/giphy.gif ?

Let me explain the most important advantages of my new best friends, stick with me, I Promise it will be worth it! (haha, silly me…)

Compared to callbacks Promises provide a more readable way of writing asynchronous code. You can simply read your chain like „At first I do this, then this and then this, ….“ and so on. And there we have the little magic word that makes Promises a lot easier to understand: „then“. The „then“ method chains further promises one after another, as often as you want, and pass the returned value of a function as the input of the next one. Even if it looks like and is read like synchronous code you are still writing asynchronous code. Yay, how cool is that?

somePromise()   // first I’ll execute somePromise()
	.then((res1) => someOtherPromise(res1))      // then I’ll pass the returned value from somePromise() to someOtherPromise() and execute this
	.then((res2) => someOtherPromiseAgain(res2))      // then I’ll pass the returned value from someOtherPromise() to someOtherPromiseAgain() and execute this
	.then(……)      // and so on….
	.then(……)
	.then(……)

Isn’t this easy to read? Yes…yes it is!

Do you want to load external content from https://media.giphy.com/media/oyLZc4i0HlosQSfnse/giphy.gif ?

And it keeps getting better: The error handling is way more detailed.

Let’s pretend our Promise from above is rejected because some condition isn’t fulfilled: The catch() method, which you can put anywhere in the Promise chain, is triggered and returns a new Promise which you’re able to handle. Just like the then() method, you can use the catch() method as often as you want in your chain.

somePromise() 
	.then((res1) => someOtherPromise(res1)) 
	.then((res2) => someOtherPromiseAgain(res2))
	.then(……) 
	.then(……)
	.then(……)
	.catch((err) => console.log(err))   // prints „Error: Oh No!“ and the error stack

If you cannot handle Promises at their worst, you don’t deserve them at their best.

Some JavaScript developer

Do you want to load external content from https://media.giphy.com/media/dQlgGuy4e2z8Rdk976/giphy.gif ?

The sweet taste of syntactical sugar

It still keeps getting better. You say: „No way!“ — I say: „await ✋“ (haha, get it?)

Whoever is a fan of syntactical sugar is definitely in the right place here because in my opinion this is the main advantage of async/await. Let’s pick the function from above again and rewrite it with async/await for explanation reasons.

/** Old **/
function somePromise() {
	return new Promise((resolve, reject) => {
		if(someCondition) {
			resolve(„Yay!“)
		} else {
			reject(new Error(„Oh no!“))
		}
	})
}

/** New **/
async function somePromise() {
	try {
		console.log(„Yay!“)
	} catch(err) {
		throw new Error(„Oh no!“)
	}
}

As you can see we describe this function as async by adding the „async“ keyword to the beginning of a function (ok, that was obvious…). The try/catch block is the alternative way to our resolve and reject from before.

  • try: Promise is resolved
  • catch: Promise is rejected

Ok so then let’s create a more realistic example. We often want to fetch some data and then decide what to do with that data. It could be possible that the code looks like this:

const somePromise = () => {
	return getJSON()
		.then(res => {
			if(someCondition) {
				return someOtherPromise(res)
			} 
		})
}

Reminds us of a callback hell, doesn’t it? With that async/await you get rid of the problem of callback hells and don’t have to deal with endless nested functions anymore. We put our Promises right in the function and „await“ their results. But be careful, you’re only allowed to use the „await“ keyword within a async function, top-level-await usage isn’t possible yet.

const somePromise = async () => {
	const a = await getJSON();
	if(someCondition) {
		const b = await someOtherPromise(a)
		return b
	}
}

The async/await version is more compact and readable because we have only two indentation levels compared to the four levels of the function without async/await. Would say: Syntactical sugar at its best.

Now that you’ve had a taste of these sweet, sweet delights, remember to brush your teeth, kids!

Thanks for the attention & stay asynchronous.

Async/Await

JavaScript

Promises

Callbacks

Call Stack

Peerigon logo