Let’s explore a common, reusable pattern to convert an event-driven API to an async/await, task-oriented one.

We can use WebSockets as example. WebSockets are simple and effortless.

Should be straightforward. But, what if we had to interface with a protocol that is not so straightforward?

Let’s imagine a fictitious, polite, and syllogistic protocol where the client needs to make its weather opinions known to the server:

Quite complex. To write an implementation in WebSockets with regular event listeners is quite clumsy. What better alternative do we have?

The answer is with async/await.

It would be nice to write this code:

Instead of:

State machine style

The flow of the program is a little less obvious. If we add any more complexity to the protocol (more weather conditions, more logic paths) then the event listener becomes more complicated.

How can we achieve a better WebSocket API? We can write an awaitable connect():

There’s more to it, but the gist is here.

Now, every message gets enqueued, waiting for someone to call receive().

The next thing to do is implement receive():

We’re done! We’re ready to await these function calls as we please.

My small library, WebSocket-async, is available:

Unpkg: https://unpkg.com/websocket-async

Npm: https://www.npmjs.com/package/websocket-async

Github PRs welcome!