Reputation: 35213
I am implementing a cache function in a computed observable.
Is there any way to invalidate the cache below if the items
collection differs since the last call?
I have seen examples of dirty checking where a serialized version of the observable is used to determine if the collection has changed, but it's too expensive for me, since there may be hundreds of items.
var itemCache;
var manipulatedItems = ko.pureComputed(function(){
var items = someObervable();
if(!itemCache /* || someObervable.hasChangedSinceLastCall */) {
itemCache = heavyWork(items);
}
return itemCache;
});
var heavyWork = function(items){
// do some heavy computing with items
return alteredItems;
};
In my viewmodel:
myViewModel.itemList = ko.pureComputed(function(){
var result = manipulatedItems();
return result;
});
Upvotes: 1
Views: 1017
Reputation: 16688
Since computed observables always cache the last value, there's no reason to store it separately. In fact, storing it separately can cause trouble with getting the latest data in your application.
var manipulatedItems = ko.pureComputed(function () {
var items = someObervable();
return heavyWork(items);
});
var heavyWork = function (items) {
// do some heavy computing with items
return alteredItems;
};
Upvotes: 2
Reputation: 63830
Yes, but you need to use .subscribe
and keep the relevant moments in vars inside your own closure. There is no "last-modified-moment" property on observables or inside ko utils to be found.
In your repro, you could do something like this:
var lastChange = new Date();
var lastCacheRebuild = null;
var itemCache;
someObervable.subscribe(function(newObsValue) { lastChange = new Date(); });
var manipulatedItems = ko.pureComputed(function(){
var items = someObervable();
if(!itemCache || !lastCacheRebuild || lastChange > lastCacheRebuild) {
lastCacheRebuild = new Date();
itemCache = heavyWork(items);
}
return itemCache;
});
As far as the repro is concerned you could even put the items = someObservable()
bit inside the if
block.
PS. This is not recursive, i.e. the subscription is only on someObservable
itself, not on the observable properties of things inside that observable. You'd have to manually craft that, which is specific to the structure of someObservable.
Upvotes: 0