Flattening an Asynchronous Javascript API

Using Promises, Proxy, and async/await, oh my


Recently, I have been working on rebuilding Neovim’s node.js API. An example interface would be something like this:

We can make it a bit more readable and “flatten” it out by using async and await (introduced in node 7). You can also read more about it from this post, ES2017’s async/await is the best thing to ever happen to JavaScript.

This is a great start, but how can we really sweeten it up? Let’s start by changing getBuffer and getLines to be getters.

OK, and what if we only cared about lines?

Awesome, right? Well, awesome until you actually try to run that code and it doesn’t work. Can you spot the problem? nvim.buffer returns a Promise and we are attempting to access the lines property of the Promise, and not the resolved value of the promise. It would be the equivalent of this (using our first example with promises).

So what can we do? One option is to have Neovim.getBuffer return a class with the interface of Buffer and Promise. Another option that comes to mind, is using a Proxy.

Putting the implementation details to the side, for now, is this a good idea? It seems very “un-javascript”, but maybe that’s a good thing. You’re able to hide the promise chain from your API consumer, but this may cause confusion since it is not explicitly clear that each of these calls returns a Promise.

Is this something you would love to see more of, or am I just crazy? I would love to hear your thoughts.