Aynı gözlemlenebilir abone olarak bir gözlemlenebilirin önceki değerini alın


86

Nakavtta, yeni değeri almadan önce, bir gözlemlenebilir aboneliğin içindeki bir gözlemlenebilirin mevcut değerini elde etmek mümkün müdür?

Misal:

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

Yanıtlar:


88

Önceki değere abone olmanın bir yolu var:

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

thisburada ne anlama geliyor?
Thanasis Ioannidis

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

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

Yukarıdakileri şu şekilde kullanın:

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

});

2
Nakavt için oldukça yeni, ancak bunun varsayılan abonelik kurulumunun bu şekilde olmasını diliyorum. Ya da .. bu fn en azından "abone ol" u ilk kez kullandığımda ilk kaşıntımı kesecek.
bkwdesign

1
Bu konuda github.com/knockout/knockout/issues/914 adresinde bazı hareketler oldu . 3.4 sürümü için planlanmış gibi görünüyor.
AlignedDev

2
Abone olunan gözlemlenebilir değer türünün bir Dizi olması durumunda, onu dilimlemeniz gerekir, aksi takdirde oldValue her zaman newValue ile aynı olacaktır. Burada çalışan bir örneği kontrol edin: jsfiddle.net/david_freire/xmk6u9yn/4
David Freire


Oh az önce git konuşmasını gördüm.
Michael

21

Beagle90 cevabında küçük bir değişiklik. Örneğin, dispose () öğesine erişebilmek için aboneliğin kendisini daima iade edin.

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

2
Bu gerçek bir adım yukarı, ancak arama .disposesadece atmayın ikinci abonelik bundan dönüş değeri üzerinde olacak değil 'beforeChange'abonelik
TRManderson

18

Çekme isteği bu özelliği eklemek daha iyi kullanarak güvenmek yerine olmak winds bazı farklı kodu vardır beforeChangeolay.

Michael Best'e çözüm için tüm övgü

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

Michael'dan alıntı yapmak için:

Başlangıçta beforeChangebu sorunu çözmek için kullanmayı önerdim, ancak o zamandan beri her zaman güvenilir olmadığını fark ettim (örneğin, valueHasMutated()gözlemlenebilir olanı ararsanız ).


3

Önceki değeri elde etmek için yazılabilir bir hesaplanmış gözlemlenebilirden peek () çağırabileceğimi buldum.

Bunun gibi bir şey (bkz. 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
Bu maalesef işe yaramıyor, çünkü abonelik geri araması çağrıldığında, değer zaten değişti ve bu nedenle peek()size yeni değeri verecektir.
Michael Teper

@MichaelTeper Cevabımı bir yıl önce gönderdiğimi biliyorum, ancak bazı olumsuz oylar aldıktan sonra test ettim ve işe yarıyor. Bakınız: jsfiddle.net/4MUWp
rjmunro

Tamam, orada ne yaptığınızı görüyorum ... Soru, subscribepeek () ile yapılamayan bir geri aramadaki değeri geri almakla ilgiliydi . Örneğiniz hiçbir şeyi kanıtlamaz ve yeni gelen birinin kafasını karıştırabilir. Temel olarak burada özel bir değişkeni sarmalıyorsunuz ve değerini ayarlamadan önce gösteriyorsunuz - bu yüzden elbette değişmeyecek.
Simon_Weaver
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.