What is LiveSet?

LiveSet is an AngularJS module that makes it easy to build real time applications. We created it so you can focus on building your app instead of cobbling together several libraries and frameworks. Unlike other real-time libraries and frameworks, we didn’t build LiveSet on top of our own proprietary protocols and transports. Instead we used the HTML5 EventSource Web API. This means you aren’t locked into our client or server and can use existing tooling (for example, Chrome’s EventStream tab–see below).

r1

Below is screen recording of several basic LiveSet examples. These examples illustrate just how much you can accomplish with LiveSet and LoopBack in 10-20 lines of JavaScript.

gif

 

The LiveSet API

The LiveSet module includes two factories you can inject into your AngularJS controllers and services.

createChangeStream(src)

This function returns a ChangeStream, which extends the Node.js PassThrough stream with some basic JSON parsing support. When you provide a src argument (an EventSource), the stream will add event listeners to it and write data from the EventSource to the stream.

LiveSet(data, changes, options)

This is the LiveSet constructor. It requires an array of initial data, and a`ChangeStream`.

Let’s see the code!

Favorite Colors

r2

This is a snippet from the colors example that demonstrates creating a basic LiveSet and wiring it to an EventSource. The Color service is generated by the loopback-angular-sdk.

var src = new EventSource('/api/colors/change-stream');
var changes = createChangeStream(src);
var set;

Color.find().$promise.then(function(results) {
  set = new LiveSet(results, changes);
  $scope.colors = set.toLiveArray();
});

Changes made using the Color service will be pushed to other clients listening on the same change-stream.

Live Draw

r4

The drawing example creates a LiveSet in a similar way. The draw method uses a service provided by the loopback-angular-sdk to create additional points in the drawing. This data is streamed to other browser clients.

$scope.draw = function(e) {
  if($scope.drawing) {
    Circle.create({
      x: e.offsetX,
      y: e.offsetY,
      r: Math.floor(10 * Math.random())
    });
  }
}

Streaming Chart

r5

The streaming chart does not use the LiveSet class at all. It demonstrates how to stream arbitrary JSON data to browser clients.

var src = new EventSource('/api/process/memory');
var changes = createChangeStream(src);

changes.on('data', function(update) {
  // add the new data to the chart
});

See the entire chart example code in the Angular LiveSet example.

Server-sent events

LiveSet uses HTML5’s EventSource web API to accept data pushed from the server (server-sent events). Other similar libraries and frameworks use WebSockets or HTTP long polling (among other strategies). LiveSet does not require HTTP requests to be upgraded to WebSockets, which means it is compatible with load balancers and proxies that don’t support WebSockets. It also means most modern browsers (see below) can receive data natively instead of requiring a large JavaScript dependency.

To send changes to objects in your LiveSet from your server, your server should support sending a `ChangeStream` using the EventSource protocol. LoopBack, the Node.js API framework, supports this natively. You can see an implementation with the /my-data/change-stream route in the example code.

Most browsers natively support EventSource and Server-sent events. For IE and other browsers that do not support it natively, you can use one of several polyfills.

Creating the Favorite Colors Example

Here is a basic tutorial that walks you through creating a simple AngularJS application using LiveSet. It assumes you are aware of setting up a basic angular application and its dependencies.

Step 1: Dependencies

You will need the following Node modules. Take a look at their getting started guides and READMEs if you are not familiar with setting them up:

Also the following Bower packages:

First you will need a basic AngularJS application running in a browser including the dependencies mentioned above. In the next steps I’ll walk through using the `lbServices` and LiveSet modules to build the application.

Step 2: The API

The Favorite Colors example was created first by running `slc loopback` to scaffold a LoopBack API server. If you are unfamiliar with creating LoopBack apps read more about it on the LoopBack site.

Using the slc CLI tool

Once you have the LoopBack API scaffolded, you can add a model. All we need for this app is a basic Color model.

slc loopback:model

Follow the CLI instructions and create the property “val”. Select “string” for the type. Add another property named “votes”. This should be a “number”.

The Color service

Generate your lb-services.js angular module using the loopback-angular-sdk. This will give you access to the Color resource in your angular app. Make sure you include the script tag and register the module as an angular dependency for the lbServices module (generated by loopback-angular-sdk). You also must include the source for the ngResource module (which you should have installed as part of step 1).

Step 3: The Controller

Now that you have a Color model API and the angular-live-set module available from your angular app, you can create a simple controller for interacting with the Color data. Start with a simple template that renders an array of color objects. I’ll assume you know how to do this. The template should look a bit like this:

<div ng-controller="ColorCtrl">
  <div ng-repeat="color in colors">
    <button
      ng-click="upvote(color.id)"
      style="background: "></button>
  </div>
</div>

Within our controller we need to create a LiveSet of colors as well as implement the `createColor()` and `upvote()` methods. It should look something like this:

function ColorCtrl($scope, createChangeStream, LiveSet, Color) {
  $scope.upvote = function(id) {
    Color.upvote({id: id});
  }

  $scope.newColor = 'red';

  $scope.createColor = function() {
    Color.create({val: $scope.newColor, votes: 0});
  }
}

And in our model source code we need to add the upvote method:

Color.upvote = function(id, cb) {
  Color.findById(id, function(err, color) {
    if(err) return cb(err);
    color.votes += 1;
    color.save(cb);
  });
};

Color.remoteMethod('upvote', {
  isStatic: true,
  accepts: {arg: 'id', type: 'number'}
});

Step 4: The LiveSet

The last step is to add the actual live set.

// this should be added to our controller
var changeStreamUrl = '/api/colors/subscription?_format=event-source';
var src = new EventSource(changeStreamUrl);
var changes = createChangeStream(src);
var set;

Color.find().$promise.then(function(colors) {
  set = new LiveSet(colors, changes);
  $scope.colors = set.toLiveArray();
});

The code above creates a LiveSet from a `ChangeStream`. The LiveSet is a read only collection of data. The items in the set will be updated as changes are written to the `ChangeStream`.  Since the change stream was created with an `EventSource` the changes will be written from the server as they are made. This will keep the data in the LiveSet up to date.

Also, the LiveSet will make sure that changes are applied to the `$scope`. This means often you can create a LiveSet as a view of the data and use the model API (eg. Color) to modify the data. Once the change has been made on the server, the change will be made to your LiveSet.

Now it’s your turn!

Now that you’ve learned what LiveSet is and how to build your first LiveSet app take a deeper look at the code or browse the API, and don’t forget to star it on github –>.