UPDATE: We released an official Angular.js library since that blog post. You can read more about it in this announcement

Front-end application frameworks have given developers the tools to build client side applications with rich user experiences. Let’s say your application is built with one of these frameworks and you want to notify connected clients that something on the server has changed – how can you do that while keeping a rich user experience? This is where Pusher and angular-pusher come into play.

Angular.js

Angular.js is a client side JavaScript framework built by Google. It provides the framework for building either small components that can be plugged into your website or entire single page applications. At the core of Angular.js is a module system that allows creating providers, services, factories, and directives.

All of these are used within controllers to create, retrieve, update, and delete data while providing nice features for manipulating the HTML DOM with little custom JavaScript code. This post won’t focus on the specifics of Angular.js, so some prior knowledge of creating and structuring an Angular.js application is recommended.

In a simple Angular.js application, data is retrieved and sent to and from a backend server through an $http or $resource service provided by the framework. Below is an example of retrieving a list of items from an API and updating the selected item using the $http service.

var ItemListController = function ($scope, $http) {
  // initialize a list of items on the scope
  $scope.items = [];

  var retrieveItems = function () {
  // get a list of items from the api located at '/api/items'
  $http.get('/api/items')
    .success(function (items) {
      $scope.items = items;
    });
  };

  $scope.updateItem = function (item) {
    $http.post('/api/items', item);
  };

  // load the items
  retrieveItems();
};
<div>
  <table>
    <tbody>
      <tr>
        <th>Name</th>
        <th>Qty</th>
        <th></th>
      </tr>
      <tr>
        <td><input type="text" /></td>
        <td><input type="text" /></td>
        <td><button type="button">Update</button></td>
      </tr>
    </tbody>
  </table>
</div>

If we needed to know when items have been updated on the server by another user, we would have to constantly poll the server to find out if the items array changed.

var ItemListController = function ($scope, $http, $timeout) {

  $scope.items = [];

  var retrieveItems = function () {
    // get a list of items from the api located at '/api/items'
    $http.get('/api/items')
      .success(function (items) {
        $scope.items = items;

        // check for item changes
        $timeout(retrieveItems, 5000);
      }
    );
  };

...
};

As you can see, we just update the items array every five seconds which isn’t something that we want to keep doing. If a user is making a lot of changes, then we don’t want to keep overwriting the items array. You could build the logic to only update changed items, but you still have the issue of polling the server every five seconds. It would be much nicer if we could subscribe to an event and wait for a notification of changes in real-time.

Making Angular.js real-time with Pusher

Using Pusher will allow us to subscribe to events triggered by other clients. First I’ll show you the simple changes needed in our ItemListController to use angular-pusher. Then I’ll show you an example of using Pusher in a Node.js server when an item is updated.

First, we need tell our Angular.js application to use angular-pusher. You can do this by either downloading the development or production files from GitHub or using bower install angular-pusher and loading them into your page with the following script tag:

<script src="bower_components/angular-pusher/angular-pusher.min.js" type="text/javascript"></script>

This should be loaded after the angular.min.js file and before your application.js script.

Now we can tell our application that we want to use the services provided in angular-pusher.min.js.

angular.module('myApp', ['doowb.angular-pusher']).

config(['PusherServiceProvider',
  function(PusherServiceProvider) {
    PusherServiceProvider
    .setToken('your_app_key')
    .setOptions({});
  }
]);

The angular-pusher module has a PusherServiceProvider that can be configured when creating your application. Here is where you can set your Pusher application key (PusherServiceProvider.setToken('token')), additional Pusher options (PusherServiceProvider.setOptions(options)), and a specific version of Pusher (PusherServiceProvider.setPusherUrl(url)). The Pusher url has a default, but it may be an older version.

Now we can use Pusher in our controller to subscribe to events and be notified when our items array changes:

var ItemListController = function($scope, $http, Pusher) {
  $scope.items = [];

  Pusher.subscribe('items', 'updated', function (item) {
    // an item was updated. find it in our list and update it.
    for (var i = 0; i < $scope.items.length; i++) {
      if ($scope.items[i].id === item.id) {
        $scope.items[i] = item;
        break;
      }
    }
  });

  var retrieveItems = function () {
  // get a list of items from the api located at '/api/items'
  console.log('getting items');
  $http.get('/api/items')
    .success(function (items) {
      $scope.items = items;
    }
  );
};

$scope.updateItem = function (item) {
  console.log('updating item');
  $http.post('/api/items', item);
};

// load the items
retrieveItems();
}

The following is an example of using Pusher with Express.js running on Node.js. Pusher isn’t restricted to just Node.js applications: there are many server libraries available to make it simple to connect to Pusher. In the Node.js server, we setup our connection to Pusher with a few lines of code and it only takes one more line of code to trigger the actual update notification:

// setup Pusher
var Pusher = require('pusher');
var pusher = new Pusher({
  appId: '12345',
  key: 'some key',
  secret: 'my secret... shhh!!!'
});

// in our express server
// setup a post route and trigger the change in Pusher
app.post('/api/items', function (req, res) {

  // get our item from the req and update the item collection
  // in a production application this would have validation and items
  // would be stored in a database.
  var item = req.body;
  items[item.id] = item;

  // tell Pusher to trigger an 'updated' event on the 'items' channel
  // add pass the changed item to the event
  pusher.trigger('items', 'updated', item);

  // respond with the changed item
  res.json(item);
});

Get Pushing

All of this code can be found here on GitHub and the gh-pages branch contains the examples that these code snippets came from. The application itself can be found here. Open it now in 2 tabs or windows and witness the power of real-time yourself!

Hopefully this article and the code samples are enough to get your Angular.js application working with Pusher. If you have any questions, our support team is always there to help either via Twitter or via your own support panel.

  • Ron Nitzsche

    Nice article, thanks

    • http://rawkes.com/ Robin Hawkes

      No problem, glad you liked it.

  • gomigomi

    Sounds a little like SignalR.

  • http://www.cnc.io Christian Haintz

    Interesting. What would be the advantages of pusher compared to a socket.io solution?

    • andrewvijay

      You read my mind!!

    • http://rawkes.com/ Robin Hawkes

      I’m Robin, Head of Developer Relations at Pusher. This is a good question, and one we get a lot.

      Primarily, the major advantage is that we handle the WebSocket technology, fallbacks, and the scaling and distribution of your messages for you. This means you don’t need to worry about the many headaches involved in building something from scratch – you can focus on building your app.

      Another advantage is that you can use Pusher on many different platforms, all at the same time, so you’re not just limited to communication between a browser and a server. Some our customers communicate between mobile apps, desktop browsers, physical hardware, and the server all at the same time, with the same API.

      We also offer features out of the box that you’d have to implement yourself in Socket.IO. For example, our authentication and Presence Channels allow you to let others know when someone else joins or leaves a channel.

      These are just a few, I suggest reading through our docs to get a better idea about how we differ: http://pusher.com/docs

      Let me know if you have any more questions!

  • Paul

    What’s the advantage over firebase.com?

    • http://rawkes.com/ Robin Hawkes

      While Firebase aims to store and distribute changes to data, we focus purely on the distribution of your messages without storage on our servers. This allows us to be incredibly flexible and simple to use.

      Did you have anything specific in mind?

      • Paul

        OK so doesn’t work offline. Sounds a bit like AWS’s SNS.

        • http://rawkes.com/ Robin Hawkes

          You wouldn’t be able to have realtime communication offline anyway, whether that’s Pusher, Firebase or someone else. We focus on making sure you can push messages to your users in realtime without having to worry about scalability and setting up complex WebSocket sever infrastructure.

          • Bramagola

            Sure you would. Its called an INTRA net, not INTERnet.

            However, Firebase is locked up tech, just like this, so getting them to give you a server to use inhouse, just like getting a server solution for Pusher, would be another conversation.

        • bmorgan2

          How does firebase.com work offline?

  • Faouzi ELYAGOUBI

    Very Good exemple Thanks !

  • Kamil Biela

    It seems that this code has memory leak. Where is unsubscribe when controller is destroyed?

    • Fabio Biondi

      As Kamil said we need a way to unsubscribe the event and angular-pusher doesn’t include it: https://github.com/doowb/angular-pusher/blob/master/angular-pusher.js

      I’m an AngularJS dev and I will use Pusher in my next project (since my Client already uses it). But I have never used it so I’m trying to understand where I might find problems (I have already worked with Firebase,socketIO and others, so I’m not new to this workflow).

      I’m thinking to update the Pusher factory in angular-pusher.js in order to support the unbind of the channel but before wasting time I would like to ask you :
      1) if you can fix it : )
      2) if you think there might be some complex issues I can’t imagine now

      Thanks in advance

      • Mike

        Filing an issue against the project on github is probably the best way to attract the right people to answer this.

        • Kamil Biela
          • Brian Woodward

            I added an unsubscribe method so it can be used in a controller to … unsubscribe.

          • Fabio Biondi

            wow.. thank you very much for being so fast : )

      • Kamil Biela

        out of curiosity I have checked pusher.js lib, and there is unbind in https://github.com/pusher/pusher-js/blob/master/src/events_dispatcher.js
        I think You could just include this lib pusher.js in head of html and use it directly (or put it in angular.module(‘…’).value(somename, pusherlibvar)). That angular-pusher doesn’t give much except async loading of lib and exposing one method.

  • thijsjacobs

    We’re using Pusher with our Angular.js app on http://piethis.com — and it’s fantastic, faster and more scaleable! Users love the realtime-ness of our app.

    • http://twitter.com/timothykrell Timothy Krell

      I would love to see you post an article on how you use pusher with angular in http://piethis.com. I’m trying to wrap my head around how to do this in our app currently.

  • venkatm

    Can any one suggest me how to develop the small example using angular and pusher.or pls share the sample example

    • http://rawkes.com/ Robin Hawkes

      Hey, you can find the code for the example application here: https://github.com/doowb/angular-pusher/tree/gh-pages

      • venkatesh m

        Hi, I got the following error, when i run the Angular pusher app.

        please guide me

        TypeError: Not a buffer

        at new Hmac (crypto.js:226:17)

        at Object.Hmac (crypto.js:224:12)

        at Object.module.exports.Pusher.createSignedQueryString (E:angular-pusher-g

        h-pagesnode_modulespusherlibpusher.js:167:43)

        at Object.module.exports.Pusher.post (E:angular-pusher-gh-pagesnode_module

        spusherlibpusher.js:84:28)

        at Object.module.exports.Pusher.trigger (E:angular-pusher-gh-pagesnode_mod

        ulespusherlibpusher.js:69:17)

        at E:angular-pusher-gh-pagesserver.js:58:10

        at callbacks (E:angular-pusher-gh-pagesnode_modulesexpresslibrouterind

        ex.js:164:37)

        at param (E:angular-pusher-gh-pagesnode_modulesexpresslibrouterindex.j

        s:138:11)

        at pass (E:angular-pusher-gh-pagesnode_modulesexpresslibrouterindex.js

        :145:5)

        at Router._dispatch (E:angular-pusher-gh-pagesnode_modulesexpresslibrou

        terindex.js:173:5)

        • http://hamiltonchapman.com Hamilton Chapman

          I think this happens when you haven’t setup your Pusher appId, key, and secret in server.js.

          var pusherConfig = {};
          try {
          pusherConfig = require(‘./pusherConfig’);
          } catch (err) {
          pusherConfig.appId = process.env.PUSHER_APP_ID;
          pusherConfig.key = process.env.PUSHER_KEY;
          pusherConfig.secret = process.env.PUSHER_SECRET;
          }

          As you can see it looks for the Pusher appId, key, and secret in environment variables and if they aren’t set then the HMAC will fail as per your error.

          Let me know if that fixes it.

          • venkatesh m

            Thanks, it is fixed.
            I was forget to keep appid,key and secret in server.js.

  • venkatesh m

    Can Any one Help me, When i running the Angular pusher application. i got the following error.

    TypeError: Not a buffer at new Hmac (crypto.js:226:17) at Object.Hmac (crypto.js:224:12) at Object.module.exports.Pusher.createSignedQueryString (E:MyAngularPusherAPPnode_modulespusherlibpusher.js:167:43) at Object.module.exports.Pusher.post (E:MyAngularPusherAPPnode_modulespusherlibpusher.js:84:28) at Object.module.exports.Pusher.trigger (E:MyAngularPusherAPPnode_modulespusherlibpusher.js:69:17) at E:MyAngularPusherAPPserver.js:50:10 at callbacks (E:MyAngularPusherAPPnode_modulesexpresslibrouterindex.js:164:37) at param (E:MyAngularPusherAPPnode_modulesexpresslibrouterindex.js:138:11) at pass (E:MyAngularPusherAPPnode_modulesexpresslibrouterindex.js:145:5) at Router._dispatch (E:MyAngularPusherAPPnode_modulesexpresslibrouterindex.js:173:5)

  • venkatesh m

    I want to build a web app using Angular pusher,in that the client is Angularjs (Angular pusher).and the server is java Prorgam(pusher java rest prog). is it Possible?. Can any one Give me suggestion. if Possible give the sample code for server using javapusher.

  • venkatesh m

    Normally How Much time it will be taken to push (trigger) a message from server to connected Clients.

    • http://rawkes.com/ Robin Hawkes

      It depends on the server and your location from the US, however it would be the latency of your server to the US East coast the normal latency to the US East coast of the connected client. For most people this happens in a matter of milliseconds.

  • Hari

    Is this paid service?

    • http://pusher.wpengine.com pusher

      It is. You can learn more on our pricing page