Question

I've created a provider for signalR in our app. I need to be able to configure the connections once, and then append functions as needed. The code below works. Except for one part. (Which I've indicated in my code sample)

Everywhere else in the app, when I want to access the token, we make use of the angular cookie service, but I'm unable to do so inside the provider. As a quick hack, I added the jquery cookie library to test that i can connects to our API if the token does exist. which it does...

Question

How do i go about retrieving the cookie/token using angular's services/helpers?

Provider

   (function () {
        'use strict';

        angular.module('app').provider('signalrSvc', signalrSvc);

        function signalrSvc() {

            var self = this;

            self.hubs = [];

            this.start = function (hubs) {

                var connection = $.hubConnection("someurl/signalr");

                // convert hubNames to actual hub proxies, and append default client communication functions
                $.each(hubs, function (idx, hub) {
                    var proxy = connection.createHubProxy(hub);

                    // a minimum of one client function needs to be registered to be able to complete the connection
                    proxy.on('pingBack', function (data) { console.log(hub.hubName + ", connected: " + data); });

                    self.hubs[idx] = proxy;
                });

                // *********************THIS IS NOT "RIGHT"***********************//
                // add security token before attmpting connect
                $.ajaxPrefilter(function (options) {
                    if (!options.beforeSend) {
                        options.beforeSend = function (xhr) {
                            var token = $.cookie(".token").replace(/"/g,'');
                            xhr.setRequestHeader('Authorization', 'Bearer ' + token);
                        };
                    }
                });
                //***************************************************************//

                // connects and run initialise for each hub
                connection.start({ transport: 'longPolling' })
                    .done(function () {
                        $.each(self.hubs, function (idx, hub) {
                            hub.invoke('initialise');
                        });
                    });
            };

            this.$get = ['filterFilter', function (filterFilter) {
                return {
                    hub: function (name) {
                        return filterFilter(self.hubs, { hubName: name }, true)[0];
                    }
                };
            }
            ];
        }

    })();

Config

   app.config(['signalrSvcProvider', function (signalrSvcProvider) {
        signalrSvcProvider.start(['global','dashboard'], 'cookie');
    }]);

Implementation

   var hub = signalrSvc.hub('dashboard');

   hub.on('getAllUnapprovedAgreements', function (data) {
            // do something
   });
Was it helpful?

Solution

The answer was much simpler than i thought.. use the right tool for the right job. IE factory. This allows me to have a single connection/hub collection, and allowed me to inject the required services

Code

(function () {
    'use strict';

    angular.module('app').factory('signalrSvc', ['$rootScope', 'common', 'permissionSvc', 'filterFilter', signalrSvc]);

    function signalrSvc($scope, common, permissionSvc, filterFilter) {

        // assign placeholders. will be converted to actual hubs
        var hubs = ['globalHub', 'dashboardHub'];

        var connection = $.hubConnection(common.serviceUrl);

        // convert hubNames to actual hub proxies, and append default client communication functions
        angular.forEach(hubs, function (hub, idx) {
            var proxy = connection.createHubProxy(hub);

            // a minimum of one client function needs to be registered to be able to complete the connection
            proxy.on('pingBack', function (data) { console.log(proxy.hubName + ", connected: " + data); });

            proxy.subscribe = function (subscription, callback) {
                proxy.off(subscription);
                proxy.on(subscription,
                    function () {
                        var args = arguments;
                        $scope.$apply(function () {
                            callback.apply(proxy, args);
                        });
                    });
            };

            proxy.publish = function (target) {
                if ($.signalR.connectionState.connected) {
                    connection.start({ transport: 'longPolling' })
                              .done(function () {
                                  proxy.invoke(target);
                              });
                }
            };

            proxy.refresh = function (target) {
                if (target == undefined) {
                    proxy.publish('requestClientRefresh');
                } else {
                    proxy.publish(target);
                }
            };

            hubs[idx] = proxy;
        });

        // add security token before attmpting connect
        permissionSvc.createPrefilter();

        // connects and run initialise for each hub
        connection.start({ transport: 'longPolling' })
            .done(function () {
                angular.forEach(hubs, function (hub) {
                    hub.invoke('initialise');
                });
            });

        var publicFunctions = {
            hub: function (name) {
                return filterFilter(hubs, { hubName: name }, true)[0];
            }
        };

        return publicFunctions;
    };
})();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top