2014-01-06 4 views
10

У меня есть приложение Angular.js, которое выполняет большой набор расчетов типа учета (доход, затраты, прибыль и т. Д.) По сложной объектной модели. Для изменения любой части объектной модели необходимо выполнить все вычисления. Кроме того, многие изменения в объектной модели могут быть сделаны непосредственно из моих шаблонов с использованием привязок - нет необходимости в промежуточном контроллере.Как узнать, когда начинается цикл (или завершение) цикла дайджест Angular.js?

Многие из результатов расчета должны отображаться на дисплее пользователю и. Например, доход отображается пользователю, но также используется для расчета прибыли (которая также отображается пользователю). Тем не менее, нет смысла вычислять доход в два раза (это сложный расчет) в каждом цикле дайджеста, поэтому очевидная оптимизация заключается в том, чтобы memoize, когда он сначала вычисляется, а затем повторно использует это memoized значение для продолжительности цикла.

Проблема в том, что мне нужно очистить эти мемуары либо в начале, либо в конце цикла дайджеста. Один из подходов состоял бы в том, чтобы контроллер мог перехватывать все возможные источники изменений и вручную обезличивать объектную модель, прежде чем приступать к вычислениям. Вместо этого я бы предпочел просто использовать привязки, которые были настроены.

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

Angular $watch documentation говорит:

Если вы хотите получать уведомления, когда $ дайджеста называется, вы можете зарегистрировать функцию watchExpression без каких-либо слушателем. (Поскольку watchExpression может выполняться несколько раз за $ переваривать цикл при обнаружении изменения, должны быть готовы для нескольких вызовов к вашему слушателю.)

Это не использовать для меня, потому что очистка memoizations на каждой итерации цикл переваривания победил бы цель их иметь в первую очередь. Мне нужно только один уведомление за цикл дайджеста.

Как я могу это сделать, или есть альтернативный подход к решению проблемы?

+0

_ "... Мне нужно очистить эти воспоминания ..." _ - Почему? – Stewie

+0

'есть альтернативный подход к решению проблемы' ... действительно непонятно, какова фактическая проблема – charlietfl

+0

Что делать, если вы создаете сервис для расчета этих затрат и т. Д. И вызываете метод расчета вручную? –

ответ

9

ОК, я думаю, что, наконец, что-то придумал, поэтому подумал, что я отвечу на свой вопрос.

Существует частный метод углов, называемый $$postDigest, который будет вызывать функцию после окончания следующего цикла дайджеста. Однако он работает только один раз, и если вы попытаетесь заставить его перенести себя рекурсивно, он перейдет в бесконечный цикл.

Чтобы обойти это, вы можете вместо этого использовать $$postDigest в сочетании с обычным $watch. Если у вас есть функция под названием fn, что вы хотите, контроллер для вызова после каждого цикла переваривать, вы бы добавить что-то вроде этого функции контроллера:

... 
var hasRegistered = false; 
$scope.$watch(function() { 
    if (hasRegistered) return; 
    hasRegistered = true 
    // Note that we're using a private Angular method here (for now) 
    $scope.$$postDigest(function() { 
    hasRegistered = false; 
    fn(); 
    }); 
}); 
... 

Это основано на a code fragment by Karl Seamon. Очевидно, что это не идеальный вариант для вызова частного метода на $scope. Надеемся, что метод $postDigestWatch по этим линиям может в конечном итоге быть добавлен в Угловое.

В комментариях к моему первоначальному вопросу возникла некоторая путаница в отношении того, почему вы хотите делать такие вещи: если вы все еще неясны, проверьте this blog post I wrote, который охватывает мой конкретный прецедент.

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