Подтвердить что ты не робот

Как остановить $наблюдать в AngularJS

Недавно у меня возникли некоторые проблемы с плагинами jQuery в директивах в Angular, которые не были правильно очищены и, следовательно, создавали утечки памяти.

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

var stopObserving = attrs.$observe('myProperty', function(newValue) {          
  updateElement(newValue);
});

Так как я думал, что он работает так же, как на $watch, но это явно не так. Согласно документам, $observe вернет функцию обратного вызова, что она, второй аргумент.

У меня есть этот тест:

describe('destroy',function(){
    beforeEach(function(){
      $scope.$destroy();
    });

    it('should have emptied the DOM node', function(){
      expect(element.text()).toBe('');
    });
    it('shouldn\'t have any more watchers', function(){
      dump(element.data().$scope.$$watchers);
      expect(element.data().$scope.$$watchers.length).toBe(0);
    });
}); 

И это не удается, потому что есть один наблюдатель. Я проверил и вызывается $destroy, и, следовательно, очистка выполняется. Однако, как я могу избавиться от этого наблюдателя?

Код, если вам интересно,

https://github.com/firstandthird/angular-popbox

4b9b3361

Ответ 1

AngularJS 1.3 и выше

В Angular 1,3 и выше $observ возвращает функцию deregister, поэтому отмена регистрации $наблюдается так же, как и для $watch:

var stopObserving = attrs.$observe(...);
stopObserving();

AngularJS 1.2 и ниже

В AngularJs 1.2 нет возможности отменить регистрацию наблюдателя, и, как вы правильно заметили, функция $observ возвращает функцию обратного вызова.

Однако в настоящее время PR открыт для изменения $watch, чтобы также вернуть функцию дерегистрации, аналогичную $watch и $on, к сожалению, это только триггером для версии 1.3 из-за изменения разрыва. PR превышает здесь: https://github.com/angular/angular.js/pull/5609

Хорошая новость: для реализации изменения требуется всего 3 новых строки кода, согласно

Ответ 2

Когда вы вызываете метод $watch(), чтобы создать привязку, функция AngularJS возвращает функцию "дерегинга". Затем эту функцию можно использовать для развязки вашего слушателя $watch() - все, что вам нужно сделать, это вызвать эту возвращенную функцию, и ваш слушатель $watch() будет удален. Чтобы увидеть это в действии, взгляните на следующий код. В этой демонстрации мы наблюдаем количество кликов, которые получает ссылка. И, если это число будет выше 5, мы собираемся показать сообщение; однако, как только сообщение будет показано, мы удалим слушателя, поскольку он больше не будет иметь никакого значения.

посетите: http://plnkr.co/edit/nciFRm9HTL3i8xYSUQJa?p=preview

Как вы можете видеть, мы сохраняем ссылку на функцию, возвращаемую оператором $watch(); то, как только $watch() срабатывает несколько раз, мы вызываем этот хранимый метод, отвязывая прослушиватель $watch(). Если вы смотрите журнал консоли, вы можете видеть, что инструкции console.log() останавливаются, как только вызывается функция "дерегинга".

Ответ 3

как временное решение, которое вы можете сделать:

var key = 'myAttr';
    attrs.$observe(key, function(newValue) {
    updateElement(newValue);
    delete attrs.$$observers[key];
});

или если вы хотите быть действительно отличным:

attrs.$observe = function(key, fn) {
    attrs.$observe(key, fn);

    return function() {
       delete attrs.$$observers[key];   
    };
}

var unobserve = attrs.$observe('myAttr', function(newValue){
    updateElement(newValue);
    unobserve();
});