在订阅同一观察值时获得观察值的先验值

有没有可能在淘汰赛中获得一个观察对象的订阅内的当前值,然后再获得新的值?

例如:

this.myObservable = ko.observable();
this.myObservable.subscribe(function(newValue){
//I'd like to get the previous value of 'myObservable' here before it's set to newValue
});
48862 次浏览

There is a way to do a subscription to the before value like this:

this.myObservable = ko.observable();
this.myObservable.subscribe(function(previousValue){
//I'd like to get the previous value of 'myObservable' here before it's set to newValue
}, this, "beforeChange");

I have found that I can call peek() from a writable computed observable to get the before value.

Something like this (see http://jsfiddle.net/4MUWp):

var enclosedObservable = ko.observable();
this.myObservable = ko.computed({
read: enclosedObservable,
write: function (newValue) {
var oldValue = enclosedObservable.peek();
alert(oldValue);
enclosedObservable(newValue);
}
});
ko.subscribable.fn.subscribeChanged = function (callback) {
var oldValue;
this.subscribe(function (_oldValue) {
oldValue = _oldValue;
}, this, 'beforeChange');


this.subscribe(function (newValue) {
callback(newValue, oldValue);
});
};

Use the above like this:

MyViewModel.MyObservableProperty.subscribeChanged(function (newValue, oldValue) {


});

Little change to Beagle90 answer. Always return the subscription itself to be able to access the dispose() for instance.

ko.subscribable.fn.subscribeChanged = function (callback) {
var oldValue;
this.subscribe(function (_oldValue) {
oldValue = _oldValue;
}, this, 'beforeChange');


var subscription = this.subscribe(function (newValue) {
callback(newValue, oldValue);
});


// always return subscription
return subscription;
};

The pull request to add this feature has some different code that winds up being better than relying on using the beforeChange event.

All credit for the solution to Michael Best

ko.subscribable.fn.subscribeChanged = function (callback) {
var savedValue = this.peek();
return this.subscribe(function (latestValue) {
var oldValue = savedValue;
savedValue = latestValue;
callback(latestValue, oldValue);
});
};

To quote Michael:

I originally suggested using beforeChange to solve this problem but have since realized that it's not always reliable (for example, if you call valueHasMutated() on the observable).