Understanding Subscription Knockout: Detecting If Located

I have a subscription management in my ko model that stores any subscriptions, intercepting them and keeping a link to them.

Then I dispose them (), but sometimes I need to figure out if sub is already configured. Is a Gb member, a subscription boolean, an active-inactive flag? I see that sometimes when I install a subscription its Gb goes false, sometimes not. Should I interpret this as a waiver of rejection?

And once I delete the subscription, is the subscription object ready for garbage collection?

EDIT: I just need to figure out if there is already a subscription, as the title says. I get the subscription in the only way I know, by keeping a link to it when I declare:

var mySub = myObservable.subscribe(function(){/*do something*/});

      

For a while after I need a way to determine if mySub is already.

function isDisposed(mySubscription) {
    // if is disposed return true else return false
}

      

I need to execute some logic based on this, not just dispose of it if it is not already disposed (or I could just call the dispose method again). Is it possible to determine the status of subscription deletion?

+3


source to share


2 answers


About hand signatures

The knockout source is compiled using the Google Closure Compiler, so only properties and methods that are explicitly exported to the source code appear in the compiled library code.

With that said, the subscription has a "private" property isDisposed

, but it is not exported. Thus, the only API exported for subscription is dispose

.

Source snapshots - ko.subscription (knockout-3.1.0.debug):

ko.subscription = function (target, callback, disposeCallback) {
    this.target = target;
    this.callback = callback;
    this.disposeCallback = disposeCallback;
    this.isDisposed = false;
    ko.exportProperty(this, 'dispose', this.dispose);
};
ko.subscription.prototype.dispose = function () {
    this.isDisposed = true;
    this.disposeCallback();
};

      

About leaks and memory computations

1) Just an interesting fact about calculations - consider the following calculated

var myObservable1 = ko.observable(true);
var myObservable2 = ko.observable('foo');

var myComputed = ko.computed(function () {
    if (myObservable1()) {
        return myObservable2() + 'bar';
    }
});

      

This example myComputed

has 2 dependencies. But if we could dispute false

before myObservable1

myComputed

, we would overestimate and after re-examination, only 1 dependency and subscription would be established myObservable2

.



Why is it located:

The explanation is how the computation is computed - it registers dependencies like this: if any observable is read (which means the type code myObservable1()

) during evaluation - computed, gets a callback with that observable, checks its id and stores it in a new dependency array. After completing the evaluation, the old array of dependencies. In our example, when myObservable1

set to false, it is myObservable2

never read - since we never enter if block. So this is not a new addiction and an old addiction.

2) Another interesting fact. Consider a snippet:

(function () {
    var myObservable = ko.observable(0);
    var myModel = {
        myComputed: ko.computed(function () {
            console.log(myObservable());
        })
    };
    myModel = undefined;
    myObservable(42); // Outputs 42
})();

      

The computed is not garbage collected because infact a reference to it exists inside its dependency.

Source code anti-aliasing - ko.computed (knockout-3.1.0.debug):

function addSubscriptionToDependency(subscribable, id) {
    if (!_subscriptionsToDependencies[id]) {
        _subscriptionsToDependencies[id] = subscribable.subscribe(evaluatePossiblyAsync);
        ++_dependenciesCount;
    }
}
...
function evaluatePossiblyAsync() {
    var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
    if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
        clearTimeout(evaluationTimeoutInstance);
        evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
    } else if (dependentObservable._evalRateLimited) {
        dependentObservable._evalRateLimited();
    } else {
        evaluateImmediate();
    }
}

      

The reference to dependentObservable is retained as the reference to valuPossiblyAsync (Closures, JS and whatever Jazz) is retained.

Oh, that's all I had to say. Hope some thought comes to mind.

+5


source


A specific way to determine if the active was active computed

is to look at how many signatures the observable has.

Here, take a look:

>>> y = ko.observable()
>>> y.getSubscriptionsCount()
0
>>> x = ko.computed(function () { y() })
>>> y.getSubscriptionsCount()
1
>>> x.dispose()
>>> y.getSubscriptionsCount()
0

      

Remember that the computation pure

getSubscriptionsCount

will be 0

when the net is computed asleep, that is, itself does not have a subscription. i.e.



>>> x = ko.pureComputed(function () { y() })
>>> y.getSubscriptionsCount()
0
>>> z = x.subscribe(console.log.bind(console))
>>> y.getSubscriptionsCount()
1

      

In other words, clean computation can be removed when they are just sleeping.

You can render the net computed by subscribing to it; if the dependency signature count is still zero, it should be removed.

+3


source







All Articles