5

I'm writing a web application using Angular.JS, which uses a backend system written in Express and Socket.IO (a Node module). I've written a factory in Angular.JS for listing Elements:

angular.module('myApp.api', ['ngResource'])
    .factory('Element', function($resource, Socket) {
        return $resource(
            'http://localhost:4000/elements/:id',
            { id : '@id' },
            { 
                update: { method: 'PATCH' }
            }
        );
    });

This factory is used in ElementCtrl and shows the elements accordingly, which works perfectly:

angular.module('myApp.element', [])
    .controller('ElementCtrl', ['$scope', 'Element', function($scope, Element) {
    var elements = Element.query();
}]);

However, I've also implemented Socket.io in the backend, which sends a message if an element is added to the elements list. I want to alter the Element factory or find some other way to handle this transparently for the controller. My client Socket.io code is as follows:

angular.module('myApp.socket', [])
    .factory('ElementRealtime', function($resource, Socket) {
        var socket = io.connect('http://localhost:4000');
        return {
            on: function (eventName, callback) {
              socket.on(eventName, function () {  
                var args = arguments;
                $rootScope.$apply(function () {
                  callback.apply(socket, args);
                });
              });
            },
            emit: function (eventName, data, callback) {
              socket.emit(eventName, data, function () {
                var args = arguments;
                $rootScope.$apply(function () {
                  if (callback) {
                    callback.apply(socket, args);
                  }
                });
              })
            },
            send: function(eventName, data, callback) {
             socket.send(eventName, data, function() {
               var args = arguments;
               $rootScope.$apply(function() {
                 if (callback) {
                   callback.apply(socket, args);
                 }
               });
             });
           }
        };
    });

In the controller, I can update the code like so:

Socket.on('connect', function (data) {
    Socket.emit('subscribe', {
        channel: 'element'
    });
});

Socket.on('message', function (data) {
    elements = Element.query();
});

Is there anyway to build just one factory/service that handles the $resource and socket part, so I just can write:

var elements = Element.someFunction();

in the controller, which calls Element.query() when an update is received on the socket end? This way, I could write an API service, which handles all the realtime updates from the backend and serves the controllers always with the latest version.

Flock Dawson
  • 1,842
  • 4
  • 22
  • 34
  • This is such a great question. Did you come up with an elegant solution yet? – mz3 Jul 02 '15 at 15:41
  • Having similar situation. Also the problem is considering that socket.io returns json objects but ngResource is using $Resouce objects – ramden Dec 26 '15 at 21:17

0 Answers0