2014/07/03

JavaScript EventSource

・どこの仕様?Server-Sent Eventsで
var source = new EventSource("/chatFeed/");

# receive messages
$scope.chatFeed.addEventListener("message", $scope.addMsg, false);
/** handle incoming messages: add to messages array */
    $scope.addMsg = function (msg) {
        $scope.$apply(function () { $scope.msgs.push(JSON.parse(msg.data)); });
    };

・サーバー側は、必ず text/event-stream という MIME type で返さなければならない。
 /** Controller action serving activity based on room */
  def chatFeed(room: String) = Action { req =>
    println(req.remoteAddress + " - SSE connected")
    Ok.feed(chatOut
      &> filter(room)
      &> Concurrent.buffer(50)
      &> connDeathWatch(req.remoteAddress)
      &> EventSource()
    ).as("text/event-stream")
  }
 
==>
handle data streams reactively
I know, the method's name "&>" can make some of you go away. Please stay! This sign is like the pipe in bash. It is very easy to understand:
fileLineStream(file) &> lineParser
==>fileLineStream(file).through(lineParser)


Server-Send Events
When we want to send events in "real time" to the browser, what technologies are available?

    polling: the browser pools the server every x milliseconds to check if there is a new message. This method is not very efficient, because a lot of requests are necessary to give the illusion to update the application in real time.
    long-polling (or Comet): the browser opens a connection to the server (for example in a iframe), and the server keeps the connection opened. When the server wants to push data to the client, it sends this data with the opened connection. The client receives the data, and opens a connection again for further messages. With this method, the browser is always showing that it is waiting for data. This technology does not scale on threaded system, as each opened connection uses a thread. In JEE environment, we need an asynchronous servlet 3.1 not to make the server exploding.
    Server-Send Events (SSE) are quite similar to Comet. The main difference is that the browser manages this connection. For example, it opens the connection again if it falls.
    WebSockets provide a bi-directional, full-duplex communications channels. It is a different protocol than HTTP.

I choose to use Server-Send Events instead of WebSockets because of the following reasons:

    I've already played with WebSockets and wanted to try something new.
    WebSockets are great and can communicate in both directions. But this technology is a new protocol, sometimes difficult to integrate in an existing infrastructure (Proxy, Load-Balancer, Firewall...) Server-Send Events, on the other hand, use the HTTP protocol. The PaaS Heroku does not support WebSockets yet, but support SSE. When pushing data from the server to clients is all what you need, SSE can be what is the most appropriate and is well supported (except in IE for the moment)