Pregunta

He codificado un ejemplo simple en el que quiero emitir / emitir un evento de un servicio y quiero que ese evento se escuche por un controlador y cambie la interfaz de usuario, pero no puedo hacer que funcione y depure el código.Parece que se detiene en el oyente, pero no ejecuta la función.

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

Servicio:

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

controlador

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

índice

<!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>

Solución:

Como informó la marca Ivarni o Walter, la llamada a la función de servicio que desencadena el evento debe colocarse después del oyente, si no, está activando un evento, lo que no puede escuchar un oyente.

Necesitamos solo cambiar el controlador de la siguiente manera:

servicio

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

¿Fue útil?

Solución

Está activando el evento antes de que haya adjuntado al oyente.

Intenta esto:

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

Otros consejos

Simplemente coloque el MANDERETEST.TEST () debajo de su oyente en su controlador, como este:

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

Usted adjunta al oyente justo después de llamar a la prueba (), y allí solo se pierde el evento.

La solución que encontré para trabajar mejor en una aplicación de tamaño mediano es crear una envoltura alrededor de la función de $ emit, y retrasar los $ emit con unos pocos milisegundos, lo suficiente para que se registren todos los eventos.

También puede introducir algunas de las golosinas más en la envoltura, como pasar a su alcance actual, o dejar que cree un nuevo alcance de los hijos del $ raotscope (que será solo un nivel debajo, por lo que todavía será rápido al propagarseHasta $ ROOTSCOPE), y use eso como el canal de datos, la destrucción de eventos después del alcance muere, etc.

Aquí está el código fuente completo: http://jsfiddle.net/gabrielcatalin/2urr7

y aquí hay un extracto:

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top