Async/Await, because promises are meant to be broken

calvintam Aug 6, 2020

Hero Image

I remembered the time I discovered promises, it's like having a cup of ice water in hell. It brings structure, reduces callback hell, it makes me think about error handling. However, while promises does wonders to code structure, complexity can really produce some really ridiculous promises chain.

 initDatabase().then((database) => { 
 	return findBooks(database).then((books) => { 
 		return getUser(database).then((user) => { 
 			return pickTop(books, user); 
		}); 
 	}); 
 });

An example of how promises can spiral out of control. Where promises that run after another promise requires a value that is not returned from the previous promise.

From the above example, the getUser function requires a reference to the database that was initialized which was before findBooks. The pickTop function also requires information of all the books provided by the findBooks function.

You can picture how this can quickly become a mess. Hence a better solution is needed, and we have gotten it with Async/Await.

Back to Basics

The whole point of promises is so that javascript can be run asynchronously, without blocking the main thread. While this is great, it requires some thinking as to how to structure your asynchronous task to fit in promises. The design is great for tasks that transforms it's value step by step, not so great when it needs more info outside of what was returned by the previous promise, as well as if/else scenarios.

What if we can write asynchronous code in the same way we write code in our usual functions?

Enter Await

When thinking about async/await, you can assume that it works the same way as promises, but way more flexible.

 async function topBooks(){
 	let database = await initDatabase();
 	let books = await findBooks(database);
 	let user = await getUser(database);
 	return pickTop(books,user);
 }

The same code as above, rewritten for async/await. Each time await is appended to a function, the js engine will wait for the function to complete before executing the next line. This makes things very easy to understand. Let's make the above code slightly more complicated:

 async function topBooks(){
 	let database = await initDatabase();
 	if(database){
 		let books = await findBooks(database);
 		let user = await getUser(database);
 		return pickTop(books,user);
 	} else {
 		return { error : "database_missing" };
 	}
 }

This code is pretty trivial for what it does, handling the case where the database connection has failed. But if it were to be written in promises, you would have to think about throwing exceptions and dealing with all the exceptions in the **.catch method. Nobody has time for that.

Summary

If you have functions previously written in promises, and if you have the luxury of additional time, there's no harm in trying to convert your promises into async/await. Debugging will be significantly easier, and you might even discover ways to reduce redundancy and simplify the existing codes.

Comments

It's a little quiet here..

© Copyright 2023 calvintam. Made with Svelte Kit