Pregunta La referencia 'this' de AngularJS en la función $ timeout no funciona


Tengo una pregunta de AngularJS que me está volviendo absolutamente loco. Tengo un servicio que se ve así (este es un ejemplo para ilustrar el problema)

var app = angular.module('test-module');

app.service('ToolService', function($timeout){

    this.doSomething = function() {
       console.log("y u no referenced as method?!?");
    }

    this.runTimeoutExample = function(){
        $timeout(function(){
            this.doSomething();
        }, 1000);
    }
})

Mi controlador se ve así:

var app = angular.module('test-module', []);

var ctrl = app.controller('main-controller', function($scope, ToolService) {

    $scope.somethingWasClicked = function() {
        ToolService.runTimeoutExample();
    }

});

Este es el problema, cuando el botón al que se hizo clic que llama $ scope.somethingWasClicked reenvía la llamada al servicio y aparece un error que dice "this.doSomething is not a function".

¿Por qué? ¿Y cómo soluciono esto? Me está costando encontrar una forma de evitar que mi código funcione de esta manera sin agregar lógica innecesaria a mi controlador.

Gracias de antemano por tu ayuda


5
2018-02-26 16:33


origen


Respuestas:


Tienes 2 opciones:

1) Usando bind() Método del objeto de función:

Cambie el contexto de la devolución de llamada de tiempo de espera, para llegar al controlador this:

this.runTimeoutExample = function(){
    $timeout(function(){
        this.doSomething();
    }.bind(this), 1000);
}

2) Crear una variable especial self, para mantener el enlace al contexto de la función de servicio principal:

var app = angular.module('test-module');

app.service('ToolService', function($timeout){
    var self = this;     
    self.doSomething = function() {
       console.log("y u no referenced as method?!?");
    }

    self.runTimeoutExample = function(){
        $timeout(function(){
            self.doSomething();
        }, 1000);
    }
})

Si cada vez usa self, estarás seguro de que no se perderá ningún contexto.

Lee mas sobre el contexto de una función.


10
2018-02-26 16:36



La función dentro del tiempo de espera tiene un alcance diferente, ya que no es una función que pertenece al controlador. Asignar this a una variable antes del tiempo de espera, y luego usar esa variable:

var app = angular.module('test-module');

app.service('ToolService', function($timeout){

this.doSomething = function() {
   console.log("y u no referenced as method?!?");
}

this.runTimeoutExample = function(){
    var self = this;
    $timeout(function(){
        self.doSomething();
    }, 1000);
}
})

2
2018-02-26 16:35



var app = angular.module('test-module',[]);

app.service('ToolService', function($timeout){

   function doSomething() {
       console.log("y u no referenced as method?!?");
    }

    this.runTimeoutExample = function(){
        $timeout(function(){
           doSomething();
        }, 1000);
    }
});
 app.controller('main-controller', function($scope, ToolService) {
   
    $scope.somethingWasClicked = function() {
    
        ToolService.runTimeoutExample();
    };

});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test-module" ng-controller="main-controller">
  
  <input type="button" value="click" ng-click="somethingWasClicked()">
  
  </div>


0
2018-02-26 16:50