Domanda

Ho codificato un semplice esempio in cui voglio emettere / trasmettere un evento da un servizio e voglio che quell'evento venga ascoltato da un controller e cambia l'interfaccia utente, ma non riesco a farlo funzionare e debug del codiceSembra fermare nell'ascoltatore ma non esegue la funzione.

http://plnkr.co/edit/eglcq7zellfkp86dyzoe?p=preview .

Servizio:

angular.module('ServiceModule', []).
service('servicetest', ['$rootScope', function($rootScope){
    this.test = function(){
      $rootScope.$emit('testevent');
    };
}]);
.

controller

angular.module('ControllerModule', ['ServiceModule']).
    controller('ControllerTest', ['$scope','$rootScope','servicetest', function($scope, $rootScope, servicetest){
      $scope.name = 'World';
      servicetest.test();
      $rootScope.$on('testevent', function(){
        $scope.name = 'Joe';
      });
    }]);
.

indice

<!DOCTYPE html>
<html ng-app="ControllerModule">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link rel="stylesheet" href="style.css" />
    <script data-require="angular.js@1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js" data-semver="1.2.16"></script>
    <script src="controller.js"></script>
    <script src="service.js"></script>
  </head>

  <body ng-controller="ControllerTest">
    <p>Hello {{name}}!</p>
  </body>

</html>
.

Soluzione:

Come marchio Ivani o Walter segnalato, la chiamata alla funzione di servizio che attiva l'evento deve essere posizionata dopo l'ascoltatore, se non si attiva un evento che non ha ancora un ascoltatore in grado di ascoltare. Abbiamo bisogno di cambiare il controller come segue:

servizio

angular.module('ControllerModule', ['ServiceModule']).
        controller('ControllerTest', ['$scope','$rootScope','servicetest', function($scope, $rootScope, servicetest){
          $scope.name = 'World';
          $rootScope.$on('testevent', function(){
            $scope.name = 'Joe';
          });
          servicetest.test();
        }]);
.

È stato utile?

Soluzione

Stai attivando l'evento prima di aver allegato l'ascoltatore.

Prova questo:

  $rootScope.$on('testevent', function(){
    $scope.name = 'Joe';
  });
  servicetest.test();
.

Altri suggerimenti

Basta posizionare il ServiceTest.Test () sotto il tuo listener nel tuo controller, come questo:

  $rootScope.$on('testevent', function(){
    $scope.name = 'Joe';
  });
  servicetest.test();
.

Allega il listener subito dopo aver chiamato il test () e lì perde solo l'evento.

La soluzione che ho trovato per funzionare meglio in un'app di medie dimensioni è quella di creare un wrapper attorno alla funzione $ emit ea ritardare i $ emetti con pochi millisecondi, appena sufficiente per tutti gli eventi da registrare. Puoi anche introdurre altri acquisti nell'avvolgimento, come passarlo il tuo attuale portata di $, o lascia che crei un nuovo ambito dei figli di $ Rootscope (che sarà solo un livello sotto in modo che sia ancora veloce quando si propaganoFino a $ Roottscope) e utilizzare quello come canale dati, distruzione degli eventi dopo lo scopo, ecc ...

Ecco l'intero codice sorgente: http://jsfiddle.net/gabrielcatalin/2urr7 Ed ecco un estratto:

/**
 * Waits a given amount of time before calling emitting
 * This works well when the event registration happens before emitting.
 *
 * @param name
 * @param fn
 * @param wait
 */
this.delayEmit = function (name, fn, wait) {
    // Because of the $scope's lifecycle the $emit(publish) happens after the $on(subscription)
    //  therefore that needs to be taken care of with a delay
    $timeout(function () {
        self.emit(name, fn);
    }, wait || 100);
}
.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top