2015-11-21 30 views
16

Mam naprawdę frustrujący problem, który nie może wydostać się na dno.Metoda klienta SignalR uruchamiana wiele razy w usłudze Angular Service

Używam SignalR do przekazywania wiadomości do urządzenia mobilnego, a metoda klienta jest uruchamiana wiele razy. Liczba uruchomień rośnie, gdy wylogowuję się, który powinien wyczyścić/zamknąć/zatrzymać połączenie.

My Hub wygląda następującym

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

i mój kod klienta wygląda następująco:

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

Zostały zweryfikowane (lub przynajmniej wierzyć mam) dodaje

  1. Metoda OnMessageCreated na moim huba jest wywoływana tylko raz.
  2. Po wylogowaniu z urządzenia mobilnego połączenie jest zamykane lub rozłączane.

Z dotychczasowych zachowań wygląda na to, że tworzone są połączenia lub metoda klienta jest rejestrowana wiele razy i pojawia się po zamknięciu połączenia, ale to nie wydaje się właściwe i nie mam nic ". mogliśmy to udowodnić.

Co jest przyczyną, lub może być przyczyną, że metoda klienta zostanie uruchomiona więcej niż jeden raz, biorąc pod uwagę powyższe informacje?

W tym momencie nie mogę sprawdzić, czy jest to kwestia kątowe lub problem SignalR

+0

Chciałbym umieścić dziennik konsoli w $ rootScope $ na (funkcja 'UserAuthenticated' (zdarzenie, dane) { initializeConnection();}); –

+0

Czym dokładnie jest problem? Że po wylogowaniu n razy 'initializeConnection' wysyła zapytania n + 1? –

Odpowiedz

1

To może okazać się, że zdarzenie UserAuthenticated jest opalanych wiele razy, ale to może być obsługiwane przez umieszczenie czek $.signalR.connectionState.disconnected okolice połączenie rozpocząć

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

    } 

} 

Edit: nie faktycznie zobaczyć, gdzie wywołać metodę OnMessageCreated?

Czy też debugowałeś sygnałR hub podczas wywoływania rozłączenia? Zakładam, że zostanie to wywołane jako normalne, gdy użytkownik się rozłączy, ale także wywołasz go pod numerem $rootScope.$on('UserLoggedOut'. Z pewnością centrala signalR nie będzie w stanie zidentyfikować użytkownika w tym momencie i dlatego pozostanie w kolekcji grupy? W takim przypadku można spodziewać się dziwnych zachowań, takich jak wielokrotne połączenia, które mają zostać podniesione do pozostałych Context.ConnectionId w połączeniach grupowych.

+0

Próbowałem tego i uwierzytelnionego użytkownika jest uruchamiany tylko raz, ale 'onMessageCreated' jest uruchamiany wiele razy – TheJediCowboy

1

Skoncentruję się na tworzeniu sterownika we właściwy sposób. Na przykład tego rodzaju sytuacje są dostępne:

Jeśli kontroler jest określony w $ routeProvider iw szablonie HTML, zostanie utworzony raz dla każdej deklaracji.

Usługi są z natury singletons, ale to, co naprawdę można łatwo zepsuć (jak ja też) jest w kontrolerów. Kiedyś byłem w sytuacji, gdy te same dane zostały pobrane cztery razy.

Chciałbym dwukrotnie sprawdzić wszystkie wywołania kontrolerów z szablonów i routeprovider itp., Wszędzie tam, gdzie są odniesienia lub potrzeby.

Posiadanie nowych instancji przy każdym wylogowaniu może odnosić się do problemu z routerem. Być może dojdzie do kontekstu, gdy kontroler, który ma tę usługę, zostaje ponownie zainicjowany. Wtedy ci kontrolerzy interpretują każde działanie, które robisz w liczbie mnogiej, a tam jest bałagan. .

Źródło:AngularJS Controller execute twice