我在我的ko模型中有一个订阅管理,通过拦截它们并保存对它们的引用来保存任何订阅。
然后我处理()它们,但是我有时需要理解是否已经处理了一个子。成员Gb是订阅对象的布尔值,是活动 - 非活动标志吗?我看到,有时当我处理订阅时,它的Gb变得虚假,有时不会。我是否必须将此解释为处置失败?
一旦我处理订阅,订阅对象就可以进行垃圾回收了吗?
编辑:我只需要了解订阅是否已经处理,如标题中所述。我以我所知道的唯一方式获得订阅,在声明时保存对它的引用:
var mySub = myObservable.subscribe(function(){/*do something*/});
我需要一种方法来确定mySub是否已经处理完毕。
function isDisposed(mySubscription) {
// if is disposed return true else return false
}
我需要在此基础上执行一些逻辑,不仅在没有处理它的情况下处理它(或者我可以简单地再次调用dispose方法)。是否有可能确定订阅处置状态?
答案 0 :(得分:5)
关于手动订阅
Knockout源代码是使用Google Closure Compiler编译的,因此只有在源代码中显式导出的属性和方法才会出现在已编译的库代码中。
据说,订阅有一个"私人"属性isDisposed
,但不会导出。因此,为订阅导出的唯一API是dispose
。
源代码一瞥 - 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();
};
关于内存泄漏和计算
1)关于计算的一个有趣的事实 - 考虑以下计算
var myObservable1 = ko.observable(true);
var myObservable2 = ko.observable('foo');
var myComputed = ko.computed(function () {
if (myObservable1()) {
return myObservable2() + 'bar';
}
});
在此示例中,myComputed
有2个依赖项。但是,如果我们要求false
myObservable1
myComputed
进行重新评估,重新评估后,它只会有1个依赖关系,而myObservable2
的订阅将被处理。
为什么要处置:
解释在于如何计算compute - 它以下列方式注册依赖项 - 如果在评估期间读取任何observable(意味着代码如myObservable1()
) - 计算得到带有此observable的回调,则检查其id和存储它在一个新的依赖数组中。评估完成后 - 处理旧的依赖关系数组。在我们的示例中,myObservable1
设置为false myObservable2
永远不会被读取 - 因为我们永远不会输入if block。因此,这不是一个新的依赖,旧的依赖性被处置。
2)另一个有趣的事实。考虑片段:
(function () {
var myObservable = ko.observable(0);
var myModel = {
myComputed: ko.computed(function () {
console.log(myObservable());
})
};
myModel = undefined;
myObservable(42); // Outputs 42
})();
垃圾收集器不会收集计算结果,因为实际上对它的引用存在于它的依赖项中。
源代码的闪光 - 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();
}
}
保留对dependentObservable的引用,因为保留了对evaluatePossiblyAsync的引用(Closures,JS和所有Jazz)。
哇,这就是我要说的。希望有些想法浮现在脑海中。