防止计算收集依赖项

时间:2013-01-30 12:19:40

标签: knockout.js computed-observable

是否有一种大致实现以下概念的好方法:

var computed = ko.computed(function() {
    readSomeObservables(); //<-- if these change, notify computed
    ko.stopCollectingDependencies();
    readSomeMoreObservables(); //<-- if these change, do not notify computed
    ko.resumeCollectingDependencies();
});

我知道peek(),但在这种情况下,计算机正在调用从外部模块提供的方法,并且如果这些方法恰好涉及可观察对象,则设计要求它纯粹是偶然的。

我有一个解决方案,大致是这样做的:

window.setTimeout(function() {
    readSomeMoreObservables();
}, 0);

但是由于显而易见的原因,这在某些情况下并不理想,并导致不良行为。

5 个答案:

答案 0 :(得分:5)

以后的访客......

3.3版已经公开了ko.ignoreDependencies(callback,callbackTarget,callbackArgs)。这是绑定处理程序处理内部使用的方法,以避免从init函数调用创建依赖项。

请参阅http://www.knockmeout.net/2015/02/knockout-3-3-released.html

答案 1 :(得分:4)

组合怎么样?为您需要阅读但不想订阅的可订阅者创建临时计算。更改它们会更新计算的温度,但这可能是一个廉价的操作。你的真实计算机读取tempComputed,并查看当前缓存的值。

// this one is updated 
// if any of the subscribeables used in readSomeMoreObservables changes
// but that is hopefully cheap
var tempComputed = ko.computed(function() {
    readSomeMoreObservables();
});


var computed = ko.computed(function() {
    readSomeObservables(); //<-- if these change, notify computed

    // do not update on readSomeMoreObservables
    tempComputed.peek(); 
});

答案 2 :(得分:2)

我有点晚了,但这是我在这种情况下使用的解决方案:

var computed = ko.computed(function() {
    var a = readSomeObservables(); //<-- if these change, notify computed
    var b;

    // capture any dependencies from readSomeMoreObservables
    // in a temporary computed, then immediately dispose
    // of it to release those captured dependencies
    ko.computed(function() { b = readSomeMoreObservables(); }).dispose();

    return a + b; // or whatever
});

这会创建一个临时计算,我们称之为readSomeMoreObservables。临时计算设置了一个新的依赖捕获帧,因此所有读取的observable都在我们的临时计算中捕获。然后我们立即处理临时计算以释放它捕获的任何依赖项。

答案 3 :(得分:1)

Knockout的依赖检测具有ko.dependencyDetection.ignore功能。如果我理解正确,您可以使用它来读取subscribeables的值而不创建对它们的依赖。

至少进行以下测试:

it('Should not subscribe to subscribeables called by ignore', function() {


    var observableInner = ko.observable('initial'),
        observableOuter = ko.observable(),
        called = 0,
        computedInner = ko.computed(function() { return observableInner(); }),
        computedOuter = ko.computed(function() { 
            called += 1;
            // read dependend
            observableOuter();

            // read ignored
            var result = ko.dependencyDetection.ignore(computedInner, null)
            expect(result).toEqual('initial');

            return true;
        });

    expect(called).toEqual(1);

    // update the one we are depending on
    observableOuter(1);
    expect(called).toEqual(2);        

    // update the inner one which should trigger an update to computedInner but not to computedOuter
    observableInner('ignore');
    expect(called).toEqual(2);
});

答案 4 :(得分:0)

如果您对这些可观察量的新值不感兴趣,为什么不在计算范围之外移动可观察量的读数呢?

http://jsfiddle.net/uUXWv/2

var observableTwoInitialState = this.observableTwo(); 

this.computed = ko.computed(function() {
    return this.observableOne() + observableTwoInitialState;
}, this);