Table of Contents generated with DocToc
@Cache
The @Cache
decorator lets you modify a getter so that it caches the result of executing the getter in an intermediate observable (under the hood). This intermediate observable will get updated only when any observables that the getter depends on are changed. This is useful if the computation in the getter is expensive.
Usage:
class C extends Disposable {
@Cache
get instanceProperty() {
}
}
Note that because @Cache
uses observables the hood, it can only be used on a class that inherits from Disposable
- this includes @Component
and @Store
, which inherit from Disposable
. This ensures that the observable is disposed whenever an instance of the class is disposed. Similarly, @Cache
can't be used on a static getter, because there's no way to dispose the observable it creates (this could lead to memory leaks).
@Cache
differs from @Memoize
in that the latter will only ever execute the getter once (never subsequently updating), whereas the former will re-evaluate the getter whenever any observables it depends on change.
To understand when to use @Cache
, let's consider a concrete example:
@Component
class MyComponent {
@Observable x;
get value() {
return f(this.x);
}
render() {
return <g>
<div>{ this.value }</div>
<div>{ this.value }</div>
</g>
}
}
Here, we have a getter (value
) that returns some function of the observable property x
. In the above example, whenever this.x
changes, the two data bindings for this.value
will be invalidated (because they depend on this.x
), and the render
method will be executed. This means that whenever this.x
changes, f(this.x)
will be executed twice.
Most of the time this is not a problem, but if f()
is an expensive computation, it would be nice to avoid executing it more often than necessary. By decorating the getter for value
with @Cache
, the result of f(this.x)
is stored in an intermediate observable, and only computed once when this.x
changes. Since the bindings to this.value
just pull directly from the intermediate observable, f(this.x)
will only be executed once whenever f(this.x)
changes.
Since @Cache
is a tradeoff - it adds to memory usage, and a bit of overhead to the getter - only use it when the computation is sufficiently expensive and/or widely used to benefit from caching.