One of the trickier parts of writing JS for the web is taming async code. Control flow abstractions for handling async JS exist but are commonly overlooked in engineering organizations, which can lead JS projects unknowingly into a labyrinth of
IIFEs, through the
pyramid of doom (
issue) and directly to
callback hell — making code brittle and prone to breakage.
Take for example the following method:
function buildLinkObject(url) {
return async(function* () {
let res = yield fetch(url);
let title = /<title[^>]*>(.*?)<\/title>/.exec(res)[1];
return {url, title}
})();
}
A function
is defined called buildLinkObject
, which return
s a Promise via a call to async
(
described in detail here). Notice how the two assignments within the generator function rely on both synchronyous and asynchronyous actions. Once the response of fetch
is assigned to res
, the Generator function will then assign title
and return an object, no callbacks necessary.
Use of async
also allows us to await the results of multiple simultaneous requests like so:
let links = [];
let deferreds = [];
let urls = ["http://www.example.org", "http://example.com/"];
urls.forEach((url) => {
deferreds.push(buildLinkObject(url));
});
deferreds.forEach((deferred, index) => {
deferred.then((res) => {
links[index] = res;
}
}
Promise.all(deferreds).then(() => {
console.log(JSON.stringify(links, null, 2));
}
Resulting in JSON like the following logged to the console:
[
{
"url": "http://www.example.org",
"title": "example.org"
},
{
"url": "http://example.com",
"title": "example.com"
}
]
The above leverages ES6 Generators, Promises, Destructuring assignments and the Fetch API to perform Ajax operations in a maintainable way without introducing too much complexity. Pretty pithy when compared with ES5. And though async functions should simplify things when ES7 lands, use the above to tame async JavaScript with ES6.
Need a working example? Check out the chat parser I created using ES6 and Babel. Looking for more depth? Check out Synchronous Asynchronous JavaScript with ES6 Generators by Chris Buttery.