60

The Joy of Using Async/Await

 5 years ago
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.
neoserver,ios ssh client

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:

bueyemF.png!webQvqUbyA.png!web

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 ?

MnuMZbq.png!webAb67JbB.png!web

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!

UBbuEvA.png!webVfyMbij.png!web

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:

mie22em.png!webmiERBzq.png!web

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?

EVZVjuu.jpg!webZNryQfJ.jpg!web

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:

ZBJryyI.png!webBvaYNzN.png!web

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:

zEN7fuJ.png!web7JJZVfe.png!web

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.

aeINreY.png!webV7Z3aya.png!web

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:

uUFBFvj.png!webzIbQNnV.png!web

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

RVBbm22.png!webQfyemiF.png!web

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:

qmEzIv6.png!webuqEBF3I.png!web

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.

MF7fErV.png!webiQV3Ir3.png!web

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:

nimMRnf.png!webiiumu2i.png!web

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?

EvQzIjq.png!webEFzM3eV.png!web

Old school try/catch will help you.

But are async/await really useful?

Imagine the following scenario:

aui6VrI.png!webm6RnIby.png!web

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 :

BvAZnuJ.png!webJVRjmeu.png!web

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:

jiemqei.png!webAbAZ3uE.png!web

See you next week with a new episode of Js Monday!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK