将SignalR与AngularJs集成

时间:2016-11-30 09:28:49

标签: angularjs signalr

我有这部分代码

        $(function () {
        //
        // Initialize section
        //
        //
        var hub = $.connection.hub,
            platformHub = $.connection.PlatformHub,
            tryingToReconnect = false,
            firstConnection = true,
            state = 'notconnected';

        hub.url = 'http://localhost:80/signalr';
        hub.logging = true;
        //
        // CLIENT METHODS SECTION
        //
        platformHub.client.hello = function (message) {
            kendoConsole.log(message);
            //Transient state variable from property bag
            kendoConsole.log('Connection Started on : ' + platformHub.state.ConnectionStartedOn);
        };
        platformHub.client.greetings = function (message) {
            kendoConsole.log(message);
        };
        //
        // START HUB 
        //
        //
        function StartHub() {
            try {

                $('#connectionstatus').html('Connecting...');
                hub.start({ transport: ['webSockets', 'longPolling', 'serverSentEvents', 'foreverFrame'] })
                .done(function () {
                    tryingToReconnect = false;
                    state = 'connected';
                    //set connected status
                    $('#connectionstatus').html('connected!');
                    kendoConsole.log('transport = ' + hub.transport.name);

                    if (firstConnection) {
                        //send hello
                        $('#send').click(function () {
                            platformHub.server.hello();
                        });

                        //subscribe to groups
                        $('#subscribe').click(function () {
                            var v = $('#group').val();
                            platformHub.server.subscribe(v);
                        });

                        //handle error on server method.
                        //Each method is a promise and has a fail method
                        $('#error').click(function () {

                            try {
                                platformHub.server
                                .raiseError()
                                .done(function () {
                                    kendoConsole.log('Raise error method called on server.');
                                })
                                .fail(function (error) {
                                    kendoConsole.error('Failed: ' + error.message);
                                });
                            } catch (error) {
                                kendoConsole.error('Error: ' + error);
                            }
                        });
                        //get Time (With return value)
                        $('#getTime').click(function () {

                            try {
                                platformHub.server
                                .getServerTime()
                                .done(function (message) {
                                    var _msg = "Current time = " + message.CurrentTime +
                                        ", utc = " + message.CurrentUtcTime +
                                        ', zone = ' + message.TimeZone.StandardName;
                                    kendoConsole.log(_msg);
                                });
                            } catch (error) {
                                kendoConsole.error('Error: ' + error);
                            }
                        });
                    }
                    //set to fase in order not to create duplicate events for buttons
                    firstConnection = false;
                })
                .fail(function (error) {
                    kendoConsole.error('An error has occurred connecting: ' + error);
                });
            } catch (error) {
                kendoConsole.error('An error has occurred connecting: ' + error);
            }
        }
        //
        // HANDLE EVENTS SECTION
        //
        //
        hub
        // TRying to reconnect event
        //
        .reconnecting(function () {
            tryingToReconnect = true;
            $('#connectionstatus').html('trying to reconnect....');
        })
        //
        // state changed
        //
        .stateChanged(function (change) {
            if (change.newState === $.connection.connectionState.disconnected) {
                tryingToReconnect = true;
            }
            else { tryingToReconnect = false;}
        })
        //
        // Rconnected event
        //
        .reconnected(function () {
            tryingToReconnect = false;
            state = 'connected';
            $('#connectionstatus').html('reconnected');
        })
        //
        // Disconnect event
        //
        //handle disconnect event. by default it will fire after 30 seconds
        // https://www.asp.net/signalr/overview/guide-to-the-api/handling-connection-lifetime-events
        //error handling https://www.asp.net/signalr/overview/guide-to-the-api/platformHubs-api-guide-javascript-client#connectionlifetime
        .disconnected(function () {
            tryingToReconnect = true;
            state = 'disconnected';
            if (hub.lastError) {
                $('#connectionstatus').html('disconnected! Reason=' + hub.lastError.message);
            }
            else {
                $('#connectionstatus').html('disconnected!');
            }
            //trying to reconnect. 
            if (tryingToReconnect) {
                setTimeout(function () {
                    StartHub();
                }, 5000); // Restart connection after 5 seconds.
            }
        })
        //
        // Slow Connection Event
        //
        .connectionSlow(function () {
            kendoConsole.log('We are currently experiencing difficulties with the connection.')
        })
        //
        // Error event
        //
        .error(function (error) {
            kendoConsole.error('An error occurred on the hub connection: ' + error);
        });

        //start hub
        StartHub();

    });

工作正常......我还创建了服务器端功能。

现在我想更改客户端代码并使用AngularJS重新创建相同的功能。因为我想在我的应用程序中只添加一次此代码,我认为应该使用服务或工厂(我认为服务更好用于此目的)。

因为我是AngularJS的新手,所以我对这怎么工作感到困惑,我在互联网上寻找一个例子但却找不到有用的东西。 任何人都可以提供一些链接或一个简单的例子,说明如何使用Angular重新创建相同的代码?

1 个答案:

答案 0 :(得分:1)

由于我在搜索相同的内容时偶然发现了这个问题,因此我想为将来的参考提供一个迟到的答案。我按照以下步骤操作:

1)已安装angular-signalr-hub => bower.json

中应出现"angular-signalr-hub": "^1.6.3"或类似内容

2)包Git页面中的后续使用指南。我的代码如下所示:

    // make sure that you reference SignalR module
    angular.module("customModule", ["SignalR"]);

    // the identifier should match HubName attribute from server side (I will also add server side highlights after client implementation)
    var hub = new Hub("Environment", {

    //client side methods
    listeners: {
        'PushNotification': function (msg) {
            console.log("Received message from hub: ", msg);
            if (!msg)
                return;

            // do something with the data received from server
        }
    },

    //server side methods
    methods: ["Subscribe", "Unsubscribe"],

    //handle connection error
    errorHandler: function (error) {
        console.error(error);
    },

    // set path to signalR. In my case, I have a service that provides the base path
    rootPath: $rootUrlService.rootUrl + "signalr",

    //TODO: check if it can be moved to a more generic place
    // handle connection change events
    stateChanged: function (state) {
        switch (state.newState) {
            case $.signalR.connectionState.connecting:
                console.log("Connecting...");
                break;
            case $.signalR.connectionState.connected:
                console.log("Connected ...");
                break;
            case $.signalR.connectionState.reconnecting:
                console.log("Reconnected ...");
                break;
            case $.signalR.connectionState.disconnected:
                console.log("Disconnected ...");
                break;
        }
    }
});

3)服务器端实现 - 我选择了a generic implementation

[HubName("Environment")]
public class EnvironmentHub : Hub
{
    // not needed, but keep them as an example
    public void Subscribe(string groupName)
    {
        Groups.Add(Context.ConnectionId, groupName);
    }

    public void Unsubscribe(string groupName)
    {
        Groups.Remove(Context.ConnectionId, groupName);
    }
}

// define a service to allow dependency injection usage
public interface ISignalRHubService<THub>
    where THub : IHub
{
    /// <summary>
    /// pushes some data for all clients within the specified group
    /// </summary>
    /// <param name="groupName">group name</param>
    /// <param name="data">data to push to clients</param>
    void PushNotification(string groupName, object data);

    /// <summary>
    /// pushes some data for all clients of this hub
    /// </summary>
    /// <param name="data">data to push to clients</param>
    void PushNotification(object data);
}

public class SignalRHubService<THub> : ISignalRHubService<THub>
    where THub : IHub
{
    #region Properties
    private readonly Lazy<IHubContext> _hub = new Lazy<IHubContext>(
        () => GlobalHost.ConnectionManager.GetHubContext<THub>()
    );

    protected IHubContext Hub => _hub.Value;
    #endregion

    #region Methods
    public void PushNotification(string groupName, object data)
    {
        Hub.Clients.Group(groupName).PushNotification(data);
    }

    public void PushNotification(object data)
    {
        Hub.Clients.All.PushNotification(data);
    }
    #endregion
}

通过DI获取ISignalRHubService<EnvironmentHub>的实例并拨打以下电话:

SignalRHubService.PushNotification(someData);