In this tutorial, you will learn about the differences between Async/Await
and Promises
when making asynchronous calls in Javascript. When code is asynchronous it simply means that it isn't executed sequentially. In Javascript, asynchronous code may nvovlde calling an API, calling code within a setTimour()
, or a setInterval()
.
When making asynchronous requests using Javascript, you have several options, callbacks, generators (yield
) , promises and async
and await
. When writing async code in Javascript, you should favour one of the newer techniques, unless you have to use an older version of ECMAScript for whatever reason🤞. As callbacks are the old skool way of making async calls, I will omit them in this tutorial. Does this raise a question, out of the approaches which one should you use when writing code?
Async/Await
Async
and Await
is the latest way that developers can write asynchronous code. Released in ECMAScript 2017, Async
and Await
is a new syntax that wraps around functions that returns promises. Using async/await is a way to structure your asynchronous code so that it is easier to read. The beauty of async
and await
is that it makes asynchronous code read like synchronous code. Anything that can make code easier to read for developers will give your project a massive quality boost in terms of readability. This is why you need to know about this stuff, improving quality should be one of your main goals whenever you write code. Below shows how to structure a function so it is asynchronous and take advantage of using async
and await
:
Let us look at what is going on here:
On Line1, the function is decorated with the
async
keyword.On Line2, the
await
keyword is used. Theawait
keyword will make the function wait until the promise resolves.On Line3, the promises
resolve
value is stored in a parameter calledresult
Async/await functions are known to be non-blocking functions. When await
is used, execution of that function call is paused until the promise is resolved. A reference to the call is added to the Javascript queue and the function will not continue and be back into the call stack until something is returned. Putting the keyword async
before a function tells the compiler that the function has to return a promise. The benefit of writing code like this is that your asynchronous code can now look and behave like synchronous code. This type of code is a lot easier to read and comprehend compared to code that has lots of nested functions. This is why async
and await
code is loved by developers. It makes it easier for them to understand what is going on within a codebase.
We now have a frame of reference on how to write asynchronous code using aync
and await. I have made a lot of comparisons between writing asynchronous code using promises and
async and await
. If you are new to Javascript and do not know what a promise is, let us now look at how promises work.
Promise
The first thing you need to understand around the async
and await
vs promise debate is that it is mainly about code style. async
and await
is a sugar-syntax wrapper around a promise. Everything that you can do when writing code that handles asynchronous calls using async
and await
you can do with a promise instead.
Understanding the philosophy of how a Promise
works can be made by comparing how a promise works in real life. A promise is simply a guarantee that something will be done in the future. Just like in real life a promise can only be kept in the future. Historically in Javascript, handling asynchronous code was done using something called a callback function. A callback function would be executed after some asynchronous operation finished executing. Code written using lots of callback functions could be very hard to read. Code that was written within deeply nested callback hell became notorious as areas within a codebase that could contain hidden and unexpected bugs.
Promises were released in 2012 to make developers lives easier 😮💨Developers pretty much universally agree that asynchronous code that is written using the promise style syntax is much easier to write compared to writing code using callback functions.
Using a promise makes it easier to track whether an asynchronous event has been executed or not. This is possible through the promise state management. At any given time, a promise can be in one of three states:
Pending: Initial State, before the event has happened. For example, when data is requested from an API, the promise
will be in a pending state until the data is returned.
Resolved: After the operation was completed successfully the resolve
method is called.
Rejected: If the operation had an error during execution, the promise fails and the rejected
method is called.
After a function is called that returns a promise, the promise can be handled in one of two ways. If the promise returns in a resolved state, you can use a function called then()
to define what should happen next in the code. If the promise is returned in a rejected state you can use a function called catch()
to define what should happen next. To create a promise, you will need to define a Promise
object with the correct constructor arguments:
In the code above, if the result of GetState()
is true
then resolve
is called and the promise returns in the resolved state. If GetState()
returns false an error is created and the promise is returned in the rejected state. The code to call that promise would be written like this:
In the code above, the then()
function is executed when the promise returns in a resolved state and the code in the catch()
function is executed when the promise returns in a rejected state.
Another useful thing to note is that a Promise
can be chained. If you call a function that returns a promise and that promise returns another promise then the then()
functions can be chain together. This type of code would look similar to this:
As long as each calling function returns a promise, this chaining can go on forever 😵💫. This promise chaining allows developers to write less code, however, promise chaining can make it harder to understand what the code is doing and follow all the different execution paths.
Async/Await Vs Promise
As long as each calling function returns a promise, this chaining can go on forever 😵💫. This promise chaining allows developers to write less code, however, promise chaining can make it harder to understand what the code is doing. This is especially true when you are trying to follow all the different execution paths.
Async/Await Vs Promise
As you can see from the two code examples, there are several differences between promises and async/await:
Most developers agree that using
async
andawait
results in more concise and easier to reason about codeAsync
andawait
allows you to wrap your code using atry
andcatch
to handle errors. This can make it easier to manage errors compared to promise rejected chaining andcatch()
The
await
keyword only works inside functions decorated with theasync
keyword. If you try to useawait
in a normal function the compiler will throw aSyntaxError
When writing asynchronous code where the results are reliant on the results from other asynchronous code, code can start to become very hard and confusing to read using a promise, take this example:
When using async
and await
the same code is much easier to comprehend and reason about:
I personally find it much easier to read the second snippet as it is written sequentially. As long as you use good naming conventions the second argument will read more like a normal sentence. Code that is written in a declarative syntax has been proved to be easier to understand compared to more imperial styled code. Basically, async
and await
makes it easier for my tiny little brain to understand what is going on 🤯
I am hoping this guide helps you understand the differences between code written using a async
and await
style compared to code written using a promise
based style. At the time of writing, when you need to write async code, use async
and await
as the developer community in general agrees that this will lead to easier to understand code!
Happy Coding 🤘