连接开始后连接到 SignalR 集线器

Jer*_*984 5 javascript asp.net signalr signalr-hub signalr.client

假设我的服务器应用程序中有两个或更多集线器。我的 javascipt 客户端(Angular SPA)最初需要连接到第一个集线器,并且需要订阅这样的方法:

connection = $.hubConnection(appSettings.serverPath);
firstHubProxy = connection.createHubProxy('firstHub');
firstHubProxy('eventFromFirstHub', function () {
        console.log('Method invokation from FirstHub');
            });
connection.start().done(function (data) {
                console.log("hub started");
            });
Run Code Online (Sandbox Code Playgroud)

一切正常。现在,我的 Angular SPA 用户可能决定在他的页面上放置一个小部件,该小部件需要订阅来自第二个集线器的方法:

secondHubProxy = connection.createHubProxy('firstHub');
secondHubProxy('eventFromSecondHub', function () {
        console.log('Method invokation from SecondHub');
            });
Run Code Online (Sandbox Code Playgroud)

第二个集线器的方法不起作用。我猜是因为它是在connection.start().

我的示例是简化的,在我的实际应用程序中,将有 20 多个中心,用户可能会或可能不会通过向其页面添加或删除小部件来订阅这些中心。

据我所知,我有两个选择:

  1. 调用 connection.stop() 然后调用 connection.start()。现在两个中心订阅都在工作。这感觉不对,因为在所有集线器上,OnConnected() 事件都会触发,我的应用程序将一直启动和停止。
  2. 为所有可能的集线器创建集线器代理对象,在所有可能的集线器上订阅一个虚拟方法,以便应用程序可以在以后根据需要订阅集线器方法。这也感觉不对,因为我需要创建 20 多个集线器代理,而我可能只需要其中的几个。

有没有人知道我可以用来完成这个的模式?还是我在这里遗漏了一些非常简单的东西?

Sta*_*ams 4

我个人使用#2。我有一个订阅所有客户端方法的中心服务。然后,我的任何其他角度组件都会拉入该集线器服务并根据需要订阅其事件。

这里是;

hub.js

(function () {
    'use strict';

    angular
        .module('app')
        .factory('hub', hub);

    hub.$inject = ['$timeout'];

    function hub($timeout) {
        var connection = $.connection.myHubName;

        var service = {
            connect: connect,
            server: connection.server,
            states: { connecting: 0, connected: 1, reconnecting: 2, na: 3, disconnected: 4 },
            state: 4
        };

        service = angular.extend(service, OnNotify());

        activate();

        return service;

        function activate() {
            connection.client.start = function (something) {
                service.notify("start", something);
            }

            connection.client.anotherMethod = function (p) {
                service.notify("anotherMethod", p);
            }

            // etc for all client methods 

            $.connection.hub.stateChanged(function (change) {
                $timeout(function () { service.state = change.newState; });
                if (change.state != service.states.connected) service.notify("disconnected");
                console.log("con:", _.invert(service.states)[change.oldState], ">", _.invert(service.states)[change.newState]);
            });

            connect();
        }

        function connect() {
                $.connection.hub.start({ transport: 'auto' });
        }
    }
})();
Run Code Online (Sandbox Code Playgroud)

通知时

var OnNotify = function () {
    var callbacks = {};
    return {
        on: on,
        notify: notify
    };

    function on(name, callback) {
        if (!callbacks[name])
            callbacks[name] = [];
        callbacks[name].push(callback);
    };

    function notify(name, param) {
        angular.forEach(callbacks[name], function (callback) {
            callback(param);
        });
    };
}
Run Code Online (Sandbox Code Playgroud)

然后我可以根据需要订阅内容,例如在控制器中;

(function () {
    'use strict';

    angular
        .module('app')
        .controller('MyController', MyController);

    MyController.$inject = ['hub'];

    function MyController(hub) {
        /* jshint validthis:true */
        var vm = this;
        vm.something = {};

        hub.on('start', function (something) {
            $timeout(function () {
                console.log(something);
                vm.something = something;
            });
        });
    }
})();
Run Code Online (Sandbox Code Playgroud)