2016-02-26 4 views
4

У меня есть вопрос AngularJS, который сводит меня с ума. У меня есть служба, которая выглядит следующим образом (это пример для иллюстрации вопроса)

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

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

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

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

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

}); 

Вот вопрос, когда кнопка, которая была нажата, что звонки $ scope.somethingWasClicked пересылает вызов службе, и я получаю сообщение об ошибке «this.doSomething не является функцией».

Почему? И как мне это исправить? Мне нелегко найти способ, чтобы мой код работал таким образом, не добавляя лишнюю логику в мой контроллер.

Заранее спасибо за вашу помощь

+0

Пожалуйста, ознакомьтесь с http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback – charlietfl

ответ

7

У вас есть 2 варианта:

1) Использование bind() метод функционального объекта:

Изменить контекст тайм-аут обратного вызова, чтобы достигнуть контроллера this:

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

2) Создать специальную переменную self, чтобы сохранить ссылку на основной контекст функции службы:

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

Если каждый раз при использовании self, вы будете уверены в том, что никакой контекст потерян не будет.

Read more о контексте функции.

+0

Это также сработало для меня, спасибо за быстрый ответ! –

+0

@the_camino Рад помочь. –

+2

Я пошел с методом связывания, потому что на самом деле есть еще один слой контекста выше таймаута в моем реальном коде, и привязка показалась мне более чистым способом передать ссылку –

2

функции внутри таймаута имеет различные сферы, как это не функция, принадлежащая к контроллеру. Назначают this переменной перед тайм-аут, а затем использовать эту переменную:

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

Это работало для меня , спасибо за быстрый ответ –

0

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>

Смежные вопросы