Dojo WebSocket

Dojo 1.6 introduces a new API for Comet-style real-time communication based on the WebSocket API. WebSocket provides a bi-directional connection to servers that is ideal for pushing messages from a server to a client in real-time. Dojo’s new dojox.socket module provides access to this API with automated fallback to HTTP-based long-polling for browsers (or servers) that do not support the new WebSocket API. This allows you start using this API with Dojo now.

The dojox.socket module is designed to be simple, lightweight, and protocol agnostic. In the past Dojo has provided protocol specific modules like CometD and RestChannels, but there are numerous other Comet protocols out there, and dojox.socket provides the flexibility to work with virtually any of them, with a simple foundational interface. The dojox.socket module simply passes strings over the HTTP or WebSocket connection, making it compatible with any system.

The simplest way to start a dojox.socket is to simply call it with a URL path:

var socket = dojox.socket("/comet");

We can now listen for message events from the server:

socket.on("message", function(event){
var data = event.data;
// do something with the data from the server
});

Here we use the socket.on() event registration method (inspired by socket.io and NodeJS’s registration method) to listen to “message events” and retrieve data when they occur. This method is also aliased to the Dojo style socket.connect().

We can also use send() to send data to the server. If you have just started the connection, you should wait for the open to ensure the connection is ready to send data:

socket.on("open", function(event){
socket.send("hi server");
});

Finally, we can listen for the connection being closed by the server or network by listening for the “close” event. And we can initiate the close of a connection from the client by calling socket.close().

The dojox.socket method can also be called with standard Dojo IO arguments to initiate the communication with the server. This makes it easy to provide any necessary headers for the requests. For example:

We can also provide alternate transports in the socket arguments object. This would allow us to use dojo.io.script.get to connect to a server. However, a more robust solution is to use the dojox.io.xhrPlugins for cross-domain long-polling, which will work properly with dojox.socket.

Auto-Reconnect

In addition to dojox.socket, we have also added a dojox.socket.Reconnect module. This wraps a socket, adding auto-reconnection support. When a socket is closed by network or server problems, this module will automatically attempt to reconnect to the server on a periodic basis, with a back-off algorithm to minimize resource consumption. We can upgrade a socket to auto-reconnect by this simple code fragment:

socket = dojox.socket.Reconnect(socket);

Using Dojo WebSocket with Object Stores

One of the other big enhancements in Dojo 1.6 is the new Dojo object store API (supercedes the Dojo Data API), based on the HTML5 IndexedDB object store API. Dojo 1.6 comes with several store wrappers, and the Observable store provides notification events that work very well with Comet driven updates. Observable is a store wrapper. To use it, we first create a store, and then wrap it with Observable:

This store will now provide an observe() method on query results that widgets can use to react to changes in the data. We can notify the store of changes from the server by calling the notify() method on the store:

We can signal a new object by calling store.notify() and omitting the id, and a deleted object by omitting the object (undefined). A changed/updated object should include both.

Handling Long-Polling from your Server

Long-polling style connection emulation can require some care on the server-side. For many applications, the server may have sufficient information from request cookies (or other ambient data) to determine what messages to send the browser. However, other applications may vary on what information should be sent to the browser during the life of the application. Different topics may be subscribed to and unsubscribed from. In these situations, the server may need to correlate different HTTP requests with a single connection and its associated state. While there are numerous protocols, one could do this very easily be defining a unique connection and adding that as a header for the socket (the headers are added to each request in the long-poll cycles). For example, we could do:

In addition, dojox.socket includes a Pragma: long-poll to indicate the first request in a series of long-poll requests to help a server ensure that the connection setup and timeout is properly handled.

We can easily use dojox.socket with other protocols as well:

CometD

To initiate a Comet connection with a CometD server, we can do a CometD handshake, connection, and subscription:

Conclusion

Dojo’s socket API is a flexible simple module for connecting to a variety of servers and building powerful, efficient real-time applications without constraints. This adds to the array of awesome new features and improvements in Dojo 1.6.

Share

Guys this is great stuff, but I have to admit I’m getting frustrated not really being able to use this ! So I have to ask : is there a way to implement these technology relatively simply under apache ? I don’t know if the partnership between Zend framework and dojo would make sense to rely on for this, but I think the community could *really* benefit from examples on how to build this kind of client/store communication using common tools (php, apache, …).
I can’t say more that I’m dying to use this very very cool stuff under my current developement framework ;-)

http://www.sitepen.com Kris Zyp

@zladivliba: I have little experience with PHP, perhaps someone else can provide an example, but I was under the impression that PHP/Apache was stuck on thread-per-connection architecture and it would be very difficult to create anything scalable directly on that stack. I think you would need a separate Comet server handler to work with a PHP app properly.

http://www.sitepen.com Dylan

@zladivliba: You might be interested in something like Hookbox (or Hosted Hookbox)… they have some really simple examples to use it with PHP, but keeps the Comet part of the picture on a separate server (or as a hosted service in the case of the hosted version).