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
});

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");

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) {

});

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;
};

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).


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);
    }
});

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.