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.