Get In Touch

Koa: The Internet’s Latest Warrior

If you’re a regular reader of this blog, you know that I think Node is big — it’s not just playing in a sandbox, but out there on the mean streets of the Internet, holding its own with ASP.NET, PHP, and Ruby on Rails.  But Node itself is just a small part of the puzzle — essentially, Node is simply providing the foundation: the ability to run JavaScript on the server.  The heavy lifting is done with the frameworks that are built upon this foundation.

One of the most popular frameworks in the Node world has been (and still is), Express.  Express is a great framework; I was impressed enough to write a book about it.  I’m pleased to announce that Express is dead.  Wait, pleased?  Yes, pleased.  Not because I have changed my mind about Express, but because Koa has arrived, and Koa is the inevitable evolution of Express.

One of the reasons I am welcoming Koa with open arms is that if you know Express, and you know ES6 (aka Harmony aka ECMAScript 2015), you know Koa.  This is no surprise, either: the author of Express, TJ Holowaychuk, is the man behind Koa.  Koa and Express are so related, as a matter of fact, that I imagine it was a difficult decision not to simply make the next version of Express what Koa is.  But there are advantages to starting fresh, and nothing seems out-of-place in Koa, so I feel that TJ has made good use of this tabula rasa.

I don’t know why TJ named this project Koa.  Certainly not after the unfortunate acronym “Kampgrounds of America“; probably after the Acacia koa, a flowering tree native to the Hawaiian islands.  According to Wikipedia, the word koa in Hawaiian means “brave, bold, fearless, or warrior.”  Yeah, let’s go with that.

So what’s so great about Koa?  And why didn’t TJ think of this years ago when he was developing Express?  The answer is ES6.  When Express was being developed, the draft specification for ES6 was still in its infancy, and it’s only within the last year or two that ES6 features of been slowly showing up in JavaScript interpreters.  It’s a different story today: as of today, Node has implemented approximately 23% of the ES6 spec (according to kangax’s excellent compatibility table).  It may not sound enough, but fortunately that 23% includes perhaps one of the most important innovations in ES6: the generator.

Before we talk about generators, let’s take a stop back and talk about the history of asynchronous programming in JavaScript.  JavaScript is certainly not the first language to support asynchronous programming (interrupts in assembly language/machine code can be considered an early form of asynchronous programming), but it is the first language to really popularize the technique.  For the uninitiated, asynchronous programming embraces the chaos of the real world.  In the real world, you can’t always predict when things are going to happen, especially when they involve humans.  You don’t know when the user is going to click on this or type that.  At its heart, asynchronous programming is the ability to say “when some thing happens, do this” (note that this is very different from “if this, do that,” which doesn’t account for timing at all).

Many intro programming courses trot out the shopworn metaphor of a recipe — for example, a recipe for egg salad.  The idea is that you have a list of ingredients (inputs), the recipe itself (the program), and you’re left with egg salad (the output).  This metaphor usually makes it explicit that the instructions in the recipe are linear: step 1, step 2, step 3, etc.  It’s a reasonable enough metaphor — accessible in that most people have cooked something at one point in their life.  However, an experienced cook knows that the reality of cooking is something different altogether.  If you were to only do things in sequence, it would take you four times as long to make that egg salad.  Key example: while the eggs are boiling, you can be chopping the celery and green onions.  Recipes are usually written such that people can generally figure out these time-saving parallel actions themselves.  Programming languages are notoriously poor at “figuring out what you mean,” and have to be explicitly told when things can be done in parallel, and when it’s okay to bring “ingredients” together: enter asynchronous programming.

In JavaScript, asynchronous execution arrived with the very first version of the language, in 1996, in the form of callbacks.  A callback is a function (aka subroutine aka procedure) that gets invoked as soon as some other thing happens.  Most commonly, that’s either time-based (run this in 1.5 seconds) or in response to user interaction (do this when the user clicks on that button).

Callbacks worked out pretty well for many years, but when JavaScript “graduated” from a simple scripting language for web pages to a language that people were developing large and complicated applications in, callbacks started to get unwieldy.  As a matter of fact, there was even a name for it: callback hell.  Callback hell was typified by code that looked like a giant triangle:

Callback hell even spawned its own memes:

To address callback hell, the promise entered the scene.  Promises didn’t do away with callbacks, but corralled them somewhat.  They improved the situation drastically, and they remain an important tool in the modern JavaScript programmer’s toolbox.  But even promises sometimes feel awkward and unnecessarily complex….

Which brings us to the conditions that were present when TJ wrote Express.  Express was all callbacks, and you could use promise libraries to mitigate callback hell.  It was a good time, and Express was loved by many (including myself).

What ES6 brings to the table — generators — completes the picture.  Generators, along with generator runners (or generator engines), callbacks, and promises finally provide all the tools you need to do something you couldn’t do without generators: program asynchronously in a synchronous fashion.

Wait, what?  All that work to get back where we started (synchronous programming)?  Not exactly.  Generators don’t get rid of asynchronous programming: they make it possible to program in a synchronous manner (which is undeniably easier), and the messy details of asynchronous execution are hidden away from sight.  The fact is, between user interaction (which is inherently asynchronous) and integrating disparate systems and services (also asynchronous), you can’t “wish away” asynchronous programming.  But you can make it easier to manage.

And there is a danger in “abstracting away” asynchronous behavior behind generators and generator runners: while it frees us from the specter of locking up the entire program while you’re waiting on some asynchronous event, it does make it easy to make things synchronous that should be run in parallel.  So its still important to know what’s going on, and the interaction between generators, generator runners, promises, and callbacks (and a new actor on the scene, a specific type of callback called a “thunk”).

So back to Koa.  Just as Express’s handling of HTTP requests was done a pipeline of callbacks, Koa handles HTTP requests with a pipeline of generators, and serves as a generator runner (it actually uses a generator runner called “co“).

The best thing about building web apps with Koa is how pleasant it is.  Once you learn the handful of techniques necessary to deal with asynchronous execution with Koa’s generator runner, you’ll wonder why you ever put up with callback hell.

Happily, the packaged functionality you came to love in Express is being ported over to Koa at a remarkable rate.  To date, I haven’t thought “oh, I need express-X” and didn’t find a corresponding “koa-X” package (and it’s easy enough to adapt Express-style middleware to Koa love).

Incidentally, there’s still one more advancement in the JavaScript language to complete the picture.  ES6 gives you generators, but you have to make your own generator runner (much as we had to use our own promise libraries prior to ES6).  The “await” keyword is scheduled for inclusion in ES7, and then we’ll have built-in generator runners too.

If you’re a programmer, and you want to know more about generators, I recommend Kyle Simpson’s excellent article The Basis of ES6 Generators.  If you want to give Koa a spin, the Koa website has most of the important information.  However, it’s not what I would call “comprehensive documentation” yet, and if you’re not already familiar with Express, you might be a little lost (in which case, you should read my book , then come back to Koa).

If you’re not a programmer, but you are wondering what impact Koa has on your business, here’s a cheat sheet.  If you’ve already decided to start developing in Node, you should be using Koa, not Express.  If you have existing products build on Express that require a lot of maintenance or are being enhanced, consider taking the time to refactor them in Koa.  If your developers are resistant to switching over to Koa because they “don’t know ES6,” ask them if they want to be employable in a year.  ES6 is happening, and if you’re a JavaScript dev working in the web world, and you don’t need ES6, your skills are going to be obsolete very quickly.  Learn it.

 

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

Leave a Comment

Subscribe to our Newsletter

Sign up to receive a monthly update from Pop Art, featuring articles, events, and news relevant to our business and the communities we serve. Your information is private and will not be sold to third parties.