Question

I find myself requiring quite often to cache data per digest cycle, for example, a map/reduce function, or deeply nested accessor. For this it would be useful to set a digest callback, to clear the cached values before/after the digest loop. Is there a "angular way" to achieve this?

Was it helpful?

Solution

One thing you can do with $rootScope.$watch is give it a function with no "listener" (so call it with just one function that doesn't return anything). This effectively allows you to be notified via your supplied function when a digest happens.

$rootScope.$watch(function() {
    // a digest is happening.
});

Per cycle this listener will be called twice, but I can't tell if I'm beginning or ending without a hack. So I can just use a flag to help me keep track of what state we're in, and when we're transitioning from in-digest to out-of-digest, we can clear our cache. In this example, I just create a service that creates a cache using $cacheFactory and returns it, but keeps track of that state and clears it at the appropriate time.

In my crude example, it seems plausible. However, right off the bat we will have problems where the digest cache might be cleared prematurely. You can see this in the console messages of that example, where one last watch statement is emitted after the cache is cleared. This is because I can't control the order of the watch to ensure the one added by my service is the very last.

However, if we look at the source for $rootScope, we see an undocumented internal function called $$postDigest, which adds some functions to a queue which is processed when the digest is complete. So, I can use the same technique, but defer cleanup using $$postDigest, as seen in this example. It works, but we're treading on thin ice playing with internal APIs. Proceed at your own risk.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top