Thursday, July 3, 2014

When you first use $.ajax() in jQuery, it is easy and tempting to set up a HTTP request/response style communication mechanism between your client and your server. Your client sends a HTTP request, it provides a handler to receive the HTTP response and the handler does something with the result. That seems fine ...

... except it breaks down pretty easily. If the server takes too long, the HTTP connection times out and the response is lost. And, when it breaks down, you hack on it, adding polling and/or subscription mechanisms. Then it breaks down some more and you hack on it some more.

Events are always better.

With events, the client sends and receives events (e.g. a JSON object).

Events are self-contained. They do not require any external information. For example, the event should not have a different meaning if it is called on one URI (e.g. /users) versus another URI (e.g. /groups). If it does, the event should be updated with that new information to keep the event self-contained. So, in our example, maybe an "domain" key is added to the event which is assigned a value of "users" or "groups". After modifying the event, the event would again be self-contained and the URI that it was sent to can be forgotten.

An event should also be disconnected from the communications mechanism: it should not matter if an event was received via a HTTP request (or HTTP response), short-polling, long-polling, JSONP, Socket.IO or even some strange new datagram mechanism (which would be session-less and not allow responses). Different communication transports should be easy to substitute.

Events work in "fire and forget" mode. Once an event is fired, it is gone. The sender does not concern itself whether the event is received or not; it lets the event delivery mechanism do its work and deliver the event with no further interaction.

But what if your code expects a response?

The event handler should receive the event, process it and then send a response event back to the original sender. A response event is new event that is created by the receiver and sent to the original sender with a reference to the original event. Usually, the events contain a unique event number which the response event can reference. The response is still a new event; it just references another event.

With HTTP, an assumption is made that every request has its own response. This assumption may not be valid when you are using long-polling instead of HTTP. With events, however, the assumption is removed; events can be sent and response events can be sent back using some other mechanism or at a much later date. HTTP relies on the response being sent back in the same HTTP connection as the HTTP request was sent. Events do not.

Events can be built on top of HTTP requests/responses. Events are sent as part of the GET query string or the POST data and any pending events can be returned in the HTTP response body. The difference is that the events returned do not need to correspond to the events sent. Arbitrary events can be sent and arbitrary events can be received in the same HTTP connection with no relationship implied between them.

Inevitably, it seems that most systems move towards an event system (or suffer through an ever growing number of hacks to add flexibility to HTTP request/response designs).

If you want my advice, consider starting any new code with events, rather than muddling through with an HTTP request/response system and converting it later.