【问题标题】:Connect to SignalR Hub after connection start连接开始后连接到 SignalR Hub
【发布时间】:2015-12-17 08:28:27
【问题描述】:

假设我的服务器应用程序中有两个或更多集线器。我的 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");
            });

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

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

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

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

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

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

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

【问题讨论】:

    标签: javascript asp.net signalr signalr-hub signalr.client


    【解决方案1】:

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

    在这里;

    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' });
            }
        }
    })();
    

    OnNotify

    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);
            });
        };
    }
    

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

    (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;
                });
            });
        }
    })();
    

    【讨论】:

    • 感谢您的示例。所以这也意味着你在你的服务器应用程序中只使用了一个 Hub?
    • 是的,但同样的“订阅所有客户端方法”适用。
    • 好的,我明白了。我将对其进行一些自定义,因此最初仅启动连接并创建集线器代理。这样我就可以让我的控制器订阅 (.on) 和取消订阅 (.off) 所需的集线器事件,而不必对所有可能的客户端方法进行硬编码(就像你在 active() 函数中所做的那样)
    • 有点离题,但我看到你使用了 angular.extend()。我不知道这样的功能。您能用几句话解释一下它的作用以及在这种情况下有什么好处吗?
    • 它被定义为here,但我正在使用它,因此我可以轻松地将OnNotify 功能附加到任何东西上——而不是按控制器/服务对其进行编码。让我可以轻松地在控制器/服务等之间进行通信。
    猜你喜欢
    • 1970-01-01
    • 2019-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    相关资源
    最近更新 更多