确定observable是否在计算中发生了变化

时间:2016-08-09 08:33:14

标签: javascript knockout.js

我在计算的observable中实现了一个缓存函数。

如果自上次通话以来items集合不同,有没有办法让下面的缓存无效?

我见过脏检查的例子,其中使用了observable的序列化版本来确定集合是否已经改变,但这对我来说太贵了,因为可能有数百个项目。

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;
};

在我的viewmodel中:

myViewModel.itemList = ko.pureComputed(function(){
    var result = manipulatedItems();
    return result;
});

2 个答案:

答案 0 :(得分:2)

由于计算的observable总是缓存最后一个值,因此没有理由单独存储它。实际上,单独存储可能会导致在应用程序中获取最新数据时出现问题。

var manipulatedItems = ko.pureComputed(function () {
    var items = someObervable();
    return heavyWork(items);
});

var heavyWork = function (items) {
    // do some heavy computing with items 
    return alteredItems;
};

答案 1 :(得分:0)

是的,但您需要使用.subscribe并将相关时刻保留在您自己的关闭内。没有"最后修改的时刻"在可观察物或在ko utils内找到属性。

在你的repro中,你可以这样做:

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;
});

就repro而言,你甚至可以将items = someObservable()位放在if块内。

PS。这是递归,即订阅仅在someObservable本身,而不是在 内可观察的事物的可观察属性上。您必须手动制作,这特定于someObservable的结构。