Метод клиентского сигнала SignalR запускается несколько раз в Angular службе

У меня очень неприятная проблема, которая, похоже, не может быть снизу.

Я использую SignalR для отправки сообщений на мобильное устройство, и клиентский метод запускается несколько раз. Количество раз, когда он срабатывает, увеличивается, когда я выхожу из системы, которая должна очищать/закрывать/останавливать соединение.

Мой концентратор выглядит следующим образом

public class MyHub:Hub
{
    private static string _groupIdentifier = "Test"
    public override Task OnConnected()
    {
        var identity =  //grab identity from auth provider
        Groups.Add(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
        return base.OnConnected();
    }

    public void OnMessageCreated(Message message)
    {
        IHubContext context = GlobalHost.ConnectionManager.GetHubContext<MessageCreatedEmitter>();
        context.Clients.Group(String.Format("{0}-{1}",_groupIdentifier, message.userId)).onMessageCreated(obj);
    }

    public override Task OnReconnected()
    {
        var identity = //grab identity from my auth provider
        Groups.Add(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
        return base.OnReconnected();
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        var identity = //grab identity from my auth provider
        Groups.Remove(Context.ConnectionId, string.Format("{0}-{1}", _groupIdentifier, identity.UserId));
        return base.OnDisconnected(stopCalled);
    }
}

и мой код клиента выглядит следующим образом:

.service('Messages',function($rootScope,$q,$log,User,ENV){
    var self = this;

    this.proxy = null;

    var initializeConnection = function(){
        self.proxy = null;
        var connection = $.hubConnection(ENV.socketEndpoint,{
            qs: {token:User.getToken()},
            logging: true,
            useDefaultPath: false
        });
        self.proxy = connection.createHubProxy('myHub');
        self.proxy.on('onMessageCreated',function(data){
          $rootScope.$emit('Messages:messageReceived',data);
        })

        connection.start().done(function(){
          $log.info('connected');
        })
    }

    var cleanupConnection = function(){
        if(self.proxy != undefined && self.proxy != null){
            self.proxy.connection.stop();
        }
    }

    $rootScope.$on('UserAuthenticated',function(event,data){
        initializeConnection();
    });

    $rootScope.$on('UserLoggedOut',function(event,data){
        cleanupConnection();
    });

    return self;
}

Я проверил (или, по крайней мере, считаю, что имею) следующие

  • Метод OnMessageCreated на моем хабе только один раз вызывается.
  • Когда я выхожу из своего мобильного устройства, соединение закрывается или отключается.

От поведения до сих пор было похоже, что соединения выполняются или клиентский метод регистрируется несколько раз и закрывается после закрытия соединения, но это не кажется правильным, и я не смог чтобы доказать это.

Что вызывает или может привести к тому, что метод клиента будет запущен более одного раза с учетом вышеприведенной информации?

В этот момент я не могу проверить, является ли это проблемой Angular или проблемой SignalR

Ответы

Ответ 1

Вполне возможно, что событие UserAuthenticated запускается несколько раз, но его можно обработать, установив проверку $.signalR.connectionState.disconnected вокруг начала соединения

var initializeConnection = function(){
    self.proxy = null;
    var connection = $.hubConnection(ENV.socketEndpoint,{
        qs: {token:User.getToken()},
        logging: true,
        useDefaultPath: false
    });
    self.proxy = connection.createHubProxy('myHub');
    self.proxy.on('onMessageCreated',function(data){
      $rootScope.$emit('Messages:messageReceived',data);
    })

    if ($.connection.hub && $.connection.hub.state === $.signalR.connectionState.disconnected){

        connection.start().done(function(){
            $log.info('connected');
        })

    }

}

Изменить: Я действительно не вижу, как вы называете метод OnMessageCreated?

Также вы отлаживаете концентратор signalR при вызове отключения? Я предполагаю, что это называется нормальным, когда пользователь отключается, однако вы также называете его $rootScope.$on('UserLoggedOut', что ваш концентратор signalR не сможет идентифицировать пользователя на этом этапе, и поэтому они останутся в вашей групповой коллекции? Если это так, вы можете ожидать, что странное поведение, такое как несколько вызовов, будет поднято до остаточного Context.ConnectionId в групповых вызовах.

Ответ 2

Я бы сосредоточился на правильном создании контроллера. Например, такие ситуации существуют:

Если контроллер указан в $routeProvider и в HTML-шаблоне, он будет создавать один раз для каждой декларации.

Услуги по сути являются одноточиями, но то, что вы действительно можете легко объединить (как и я, тоже), находится в контроллерах. Я когда-то был в ситуации, когда одни и те же данные были получены четыре раза.

Я бы дважды проверял все вызовы контроллеров от шаблонов и маршрутизатора и т.д., везде, где вы ссылаетесь или нуждаетесь в нем.

Наличие новых экземпляров при каждом выходе из системы может относиться к проблеме маршрутизатора. Возможно, приходя в корневой каталог /, контроллер, имеющий службу, получает инициализацию снова и снова. Затем эти контроллеры интерпретируют каждое действие, которое вы делаете во множественном числе, и беспорядок там.

Источник: Контроллер AngularJS выполняется дважды