JavaScript has always had problems with having 8-indent deep nested functions due to its lack of good async support but in ES7, that has finally come to a change! I am surprised at how unpopular this is, but it seriously deserves some more attention so I thought I’d write about it.
JavaScript has always had problems with having 8-indent deep nested functions due to its lack of good async support but in ES7, that has finally come to a change! I am surprised at how unpopular this is, but it seriously deserves some more attention so I thought I’d write about it.
But before you get all excited, make sure you’re transpiling with something like babel. Native support is scarce so you’ll need to run this through a transpiler to get browser-friendly code. AFAIK, Node doesn’t have much support yet either.
Already transpiling? Then you’re good to go. Additionally if you’re familiar with generators these new keywords should come naturally to you
#What is this?
So they are two new keywords: async
and await
. Here’s an example
snippet:
async function ByeByeCallbackHell(arg) {
let Response = await doAsyncThing(arg);
return Response;
}
ByeByeCallbackHell("special argument");
Uh… what? Hopefully I didn’t lose you but the above demonstrates how
async
/await
works. I’ll explain this…
#General Usage
You can use it by adding async
before the function
keyword when
creating a function. Basically async
& await
are based of
promises. You could even consider them semantic & syntax sugar for
longer promise syntax.
Important bit:await
can only be used in a function declared
with async
#Exactly how can I use it?
Everything I’ve seen on the internet describing these give horrible
vague examples so you have no idea how to exactly implement it in your
own code. Essentially await
waits for a promise to resolve or
successfully complete. If it rejects or errors, it will… well…
error. So here’s a full example:
const fs = require("fs");
// Here's our async function
// which we can use with await
async function ReadFile(filename) {
return new Promise(
(resolve, reject) => fs.readFile(filename,
(error, data) => error ? reject(error) : resolve(data)
)
);
}
This is a function we can use with await
as it returns a promise.
If it gets resolved, we will be able to assign the argument passed to
resolve
(in this case data
), and do stuff with it, if it errors, we
can catch that in a try..catch
block.
So you can use your previous function like this:
// Example function
async function ParseAJson() {
try {
// Calls our async function
let data = await ReadFile("path/to/file.json");
let result = JSON.parse(data);
return Promise.resolve(result); // I'll expand more on this
} catch(error) {
// Promise was rejected
throw error;
}
}
If you have previous JS experience and have been paying attention, you
should understand how this works, but what’s up with the
Promise.resolve
? Well remember this is a async function. In an
async
function you should return a promise. Why? this is because
this is an asynchronous function, meaning in order to be able to
continue the async chain, you should wrap the value in a promise.
Promise.resolve(foo)
is roughly equivalent to:
new Promise(resolve => resolve(foo));
#Conclusion
Questions? Leave a comment! Make sure you’ve read the Promise
docs
if you’re confused on Promises.