Uzyskaj poprzednią wartość obserwowalnego w subskrypcji tego samego obserwowalnego

85

Czy w knockout można uzyskać bieżącą wartość obserwowalnego w ramach subskrypcji tego obserwowalnego, zanim otrzyma nową wartość?

Przykład:

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
});
KodeKreachor
źródło

Odpowiedzi:

88

Istnieje sposób na zrobienie subskrypcji wartości przed w następujący sposób:

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");
RP Niemeyer
źródło
co thistu oznacza?
Thanasis Ioannidis
151
ko.subscribable.fn.subscribeChanged = function (callback) {
    var oldValue;
    this.subscribe(function (_oldValue) {
        oldValue = _oldValue;
    }, this, 'beforeChange');

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

Użyj powyższego w ten sposób:

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

});
JBeagle
źródło
2
dość nowy do nokautu, ale żałuję, że nie jest to sposób skonfigurowania domyślnej subskrypcji. Albo ... ten fn przynajmniej podrapie mnie po raz pierwszy, gdy użyję „subskrybuj” po raz pierwszy.
bkwdesign
1
Doszło do pewnego ruchu na github.com/knockout/knockout/issues/914 . Wygląda na to, że ma to być wydanie 3.4.
Wyrównany
2
W przypadku, gdy subskrybowanym obserwowalnym typem wartości jest Array, musisz go wyciąć, w przeciwnym razie oldValue będzie zawsze taka sama jak newValue. Sprawdź działający przykład, tutaj: jsfiddle.net/david_freire/xmk6u9yn/4
David Freire
1
Fajne. Dodano wartość zwracaną, która jest obiektem subskrypcji z dispose()funkcją gist.github.com/30ff1f5c1adf215179b0046515f86e45
Michael
Właśnie widziałem rozmowę z dupkiem.
Michael,
21

Niewielka zmiana w odpowiedzi Beagle90. Zawsze zwracaj samą subskrypcję, aby na przykład mieć dostęp do metody dispose ().

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;
};
Andries
źródło
1
To prawdziwy krok naprzód, ale wywołanie .disposewartości zwracanej z tego spowoduje usunięcie tylko drugiej subskrypcji, a nie 'beforeChange'subskrypcji
TRManderson
18

Wniosek wyciągnąć , aby dodać tę funkcję ma jakiś inny kod, który nakręca bycia lepszym niż polegać na użyciu beforeChangezdarzenia.

Wszystko dzięki rozwiązaniu Michaelowi Bestowi

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

Cytując Michaela:

Początkowo sugerowałem użycie beforeChangedo rozwiązania tego problemu, ale od tego czasu zdałem sobie sprawę, że nie zawsze jest to niezawodne (na przykład, jeśli wywołujesz valueHasMutated()obserwowalne).

James Johnson
źródło
3

Odkryłem, że mogę wywołać funkcję peek () z zapisywalnego, obliczonego obserwowalnego, aby uzyskać poprzednią wartość.

Coś takiego (patrz 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);
    }
});
rjmunro
źródło
1
To niestety nie działa, ponieważ w momencie wywołania wywołania zwrotnego subskrypcji wartość już się zmieniła, więc peek()otrzymasz nową wartość.
Michael Teper,
@MichaelTeper Wiem, że opublikowałem swoją odpowiedź rok temu, ale po kilku negatywnych opiniach właśnie ją przetestowałem i działa. Zobacz: jsfiddle.net/4MUWp
rjmunro
Ok, widzę, co tam zrobiłeś ... Pytanie dotyczyło pobrania wartości w subscribewywołaniu zwrotnym, czego nie można zrobić za pomocą peek (). Twój przykład niczego nie udowadnia i może zmylić nowo przybyłego. Zasadniczo zawijasz tutaj zmienną prywatną i wyświetlasz jej wartość przed jej ustawieniem - więc oczywiście się nie zmieni.
Simon_Weaver