Ottieni il valore precedente di un osservabile nella sottoscrizione dello stesso osservabile


85

È possibile in knockout ottenere il valore corrente di un osservabile all'interno di una sottoscrizione a quell'osservabile, prima che riceva il nuovo valore?

Esempio:

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

Risposte:


88

C'è un modo per fare un abbonamento al valore prima in questo modo:

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

cosa thissignifica qui?
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);
    });
};

Usa quanto sopra in questo modo:

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

});

2
abbastanza nuovo per knockout, ma mi auguro che questo sia il modo in cui è stato impostato l'abbonamento predefinito. Oppure ... questo fn graffierà almeno il mio primo prurito quando uso "iscriviti" per la prima volta.
bkwdesign

1
C'è stato qualche movimento su questo su github.com/knockout/knockout/issues/914 . Sembra che sia previsto per la versione 3.4.
Allineato il

2
Nel caso in cui il tipo di valore osservabile sottoscritto sia un Array, è necessario tagliarlo, altrimenti oldValue sarà sempre uguale a newValue. Controlla un esempio funzionante, qui: jsfiddle.net/david_freire/xmk6u9yn/4
David Freire

1
Freddo. Aggiunto un valore di ritorno che è un oggetto di sottoscrizione con una dispose()funzione gist.github.com/30ff1f5c1adf215179b0046515f86e45
Michael

Oh, ho appena visto la conversazione git.
Michael

21

Piccola modifica alla risposta Beagle90. Restituisci sempre l'abbonamento stesso per poter accedere a dispose (), ad esempio.

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
Questo è un vero passo avanti, ma invocare .disposeil valore di ritorno da questo eliminerà solo il secondo abbonamento, non l' 'beforeChange'abbonamento
TRManderson

18

La richiesta pull per aggiungere questa funzionalità ha un codice diverso che finisce per essere migliore rispetto all'utilizzo beforeChangedell'evento.

Tutto il merito per la soluzione a 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);
    });
};

Per citare Michael:

Inizialmente ho suggerito di utilizzare beforeChangeper risolvere questo problema, ma da allora ho capito che non è sempre affidabile (ad esempio, se chiami valueHasMutated()l'osservabile).


3

Ho scoperto che posso chiamare peek () da un osservabile calcolato scrivibile per ottenere il valore precedente.

Qualcosa di simile (vedi 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
Questo non funziona, sfortunatamente, poiché nel momento in cui viene chiamata la richiamata di sottoscrizione, il valore è già cambiato e quindi peek()ti darà il nuovo valore.
Michael Teper

@MichaelTeper So di aver pubblicato la mia risposta un anno fa, ma dopo aver ricevuto alcuni voti negativi, l'ho appena testato e funziona. Vedi: jsfiddle.net/4MUWp
rjmunro

Ok, vedo cosa hai fatto lì ... La domanda riguardava il recupero del valore in un subscribecallback che non può essere fatto con peek (). Il tuo esempio non prova nulla e potrebbe confondere un nuovo arrivato. Fondamentalmente stai avvolgendo una variabile privata qui e visualizzi il suo valore prima di impostarlo, quindi ovviamente non sarà cambiato.
Simon_Weaver
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.