The Joy of Using Async/Await
source link: https://www.tuicool.com/articles/hit/iiAZruB
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
JavaScript is an event driven language . This means that JS will keep executing code while listening to other events.
Ok, I know, this may not sound so clear, so take an example:
As you can see, JavaScript executes the functions above in order. But are you sure that it will wait until function one
has terminated, before executing function two
?
Wow! Other languages such as PHP, Ruby and Python would have waited until function one
had finished before executing the next function, but JavaScript did not.
So, what if you need to make sure that function two
will be called in the right order, after the function one
?
Callbacks to the rescue!
Now take a look at the function above: we added an argument called callback
which is a function that will be executed after printing 1
to the console.
That way, we are sure that the function two
will be executed after logging 1
.
While this may seems a little bit confusing, let’s see another example:
Let’s analyze the code below:
we declared a function called getUsers
which accepts a callback function as argument. It will perform an AJAX request, and when it will be done, will invoke the callback function passing the AJAX response.
We declared a second function called printUsers
which acceps a generic argument (it can be a string, integer, an object etc…), and it ill just print that argument to the console.
We will invoke the getUser
method passing printUsers
as callback so, as you can see, it will be ready to print users to the console once the HTTP Request will have a response.
Great but… what are the disavantages of this approach?
This is called The Pyramid of Doom or Callback Hell .
While using callbacks will ensure that your code will be executed in a certan way, it will be harder to maintain and scale your code.
So here comes the Promise monad .
Using Promises
MDN describes Promises in the following way:
The Promise
object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
Let’s see how it looks:
Wow, we do not longer need to pass a callback to myFirstPromise
to execute the code synchronously !
We just need to return a new instance of the Promise object and resolve it once we got our desidered value.
We use then
in order to use the resolved value, once it’s ready.
Real world example
A great use case for the Promise monad is the fetch
api:
As you can see, the fetch
api returns a Promise by default.
That way, we can call a REST API service and once we got the response back, we can log it to the console.
If the request fails for any reason, we will use catch
in order to handle the error.
The problem
Promises are awesome. They helps developer to write more straightforward code which is self-describing, declarative and more maintainable, but they can lead to a big problem:
The scope of a promise-resolved value.
As you can see, result
and error
only exists in then
and catch
methods.
So what if we need to get multiple Promise results?
Let’s say we want to call the yesno.wtf/api
REST API 5 times and put them inside an array.
We could do so:
Hey, what happened here?
We invoked the callApi
method 5 times but once we tried to log the array arr
value, we still got the empty array back.
If we wait 5 seconds, we get the desidered array.
That’s because all the HTTP requests we made were asynchronous, so each of them takes different time to give us a response. We dont’ know how long a service will take to give us back a response .
So what can we do?
Aync/Await solves this problem
Declaring an async
function, we are able to use the await
keyword.
As you can see, we’re not using then
anymore, as we do not longer need it.
Inside of our for loop, we’re assigning the fetch
response to a constant value, then pushing it into an array.
When the loop finishes, we are able to log our arr
array.
Let’s take another example:
Let’s assume we have a todoList.txt
file and we want to read its content.
As you can see, using the fs
Node API we have to use a callback function which returns an error (for example if file does not exist) and the file content.
We won’t be able to get the file content outside the callback.
Wrapping the fs
API inside a Promise will allow us to use then/catch
, but we can’t still use data
outside the Promise.
Let’s do a bit of refactoring:
Wow! We’re able to use data
whenever we want inside the readAndPrint
function!
And what if we got an error? How can we handle it?
Old school try/catch
will help you.
But are async/await really useful?
Imagine the following scenario:
How would you handle the situation above using Promises or callbacks?
I know, it’s just a little example, but imagine you have to get data from different webservices. It would be harder without async/await
!
Also about webservices, async/await
also helps a lot writing efficient REST API. Just think about Koa :
This is a small webserver written in pure JavaScript and uses async functions to avoid callback hell. You can easily integrate any kind of query, webservice or any other stuff inside that async function:
See you next week with a new episode of Js Monday!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK