All experts blogs

The Miracle of Generators

"But can't we just use async/await?" In short. Yes. But don't you want to know what is going on behind the scenes?

This was the only question that followed an hour-long, mind-bending talk from Bodil Stokke where she explained and demonstrated the power of ES2016's iterator and generator features.

I'll admit it, this talk was a little out-dated. ES2016 is already more than 1 year old, and ES2017 was released a couple of months ago. But the ability to write asynchronous Javascript is so awesome that its no wonder we are still talking about it more than 1 year later.

For the non-developers, asynchronous code is when you delay the execution of a program until a different part of it is complete. An example could be when you want to wait for a response from the server or for a complex calculation to be completed. The key word here is "wait." Before ES2016, the most common way to simulate "waiting" was with callback functions, which eventually led to "callback hell." Believe me, it is as bad as it sounds.

With ES2016 we got promises, yield, iterators and generators and with ES2017, async/await. All ways that build asynchronicity into the Javascript core, without callbacks. In my experience, promises are the most widely used asynchronous feature, followed by async/await. In fact, before watching this presentation, I had never written an iterator/generator, nor had I seen one in the wild.

I'm sorry for the code, but I feel i would be doing an injustice to the presentation (which was one hour of playing with the command line) if I didn't.

With promises, you can do this...
return getItems()
  .then((items) => /* do something with the items */)
  .catch((err) => /* do some error handling */)

That is pretty good. the getItems function will return a promise that, when resolved, will trigger then or when rejected will trigger catch. But the functions passed to then and catch look very similar to a callback.

With Generators, we can take it one step further and wait for multiple promises to resolve sequentially with the yield keyword...
let generator = function* () {
  let items = yield getItems(); // pauses until getItems() returns    
  let item = yield filterItems(id, items.value); // pauses until filterItems() returns

let iterator = generator();; // { value: {items}, done: false }; // { value: {item}, done: false }; // { value: undefined, done: true }

/* the sequential next calls above can be programatically abstracted, but thats too much for this blog. And that is almost exactly what async/await does. */

With async/await...
async function getItemById(id) {
  let items = yield getItems(); // execution will pause until getItems returns
  let item = yield filterItems(id, items); // execution pauses until filterItems returns
  return item;

// strikingly similar to the generator above...

Before this presentation, I had never written a generator function. And I may never have to.

With the frontend ecosystem evolving at break-neck pace, it is difficult to keep up with every development, much less understand the inner workings of all new features. However, these asynchronous features are game-changing, and a deeper understand of them is essential to writing elegant javascript.

In summary, new features officially added to Javascript in the last 14 months have made writing asynchronous programs much easier. With more and more business logic being implemented in the frontend, this will make handing complex tasks easier. But learning how to use these new features is not enough. We should strive to learn how they work as well.

Sitecore Cortex: How Smart is it Really?

How smart are content management systems? And what do you need to do to reap the benefits from it? We looked behind the marketing facade and put Sitecore Cortex to the test.