Отримати попереднє значення спостережуваного в підписці на таке саме спостережуване


85

Чи можливо в нокауті отримати поточне значення спостережуваного в підписці на це спостережуване, перш ніж воно отримає нове значення?

Приклад:

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

Відповіді:


88

Існує спосіб зробити передплату на значення before таким чином:

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

що thisозначає тут?
Танасіс Іоаннід

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

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

Використовуйте вищезазначене так:

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

});

2
досить новий для нокауту, але я бажаю, щоб це був спосіб налаштування підписки за замовчуванням. Або .. цей fn принаймні подряпає мій перший свербіж, оскільки я вперше використовую "підписатися".
bkwdesign

1
Щодо цього відбувся певний рух на github.com/knockout/knockout/issues/914 . Схоже, він запланований для випуску 3.4.
Вирівняні

2
Якщо підписаним спостережуваним типом значення є масив, вам доведеться нарізати його, інакше oldValue завжди буде таким самим, як newValue. Перевірте робочий приклад тут: jsfiddle.net/david_freire/xmk6u9yn/4
Девід Фрейр

1
Класно. Додано повернене значення, яке є об’єктом передплати з dispose()функцією gist.github.com/30ff1f5c1adf215179b0046515f86e45
Майкл

О, щойно побачив розмову git.
Майкл

21

Невелика зміна відповіді Beagle90. Завжди повертайте саму передплату, щоб мати можливість отримати доступ до 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
Це справжній крок вперед, але .disposeвикористання зворотного значення з нього призведе до позбавлення лише від другої передплати, а не від 'beforeChange'підписки
TRManderson

18

Запит тягнути , щоб додати цю функцію , має деякий інший код , який намотує підсумку краще , ніж покладатися на використанні beforeChangeподії.

Вся честь за рішення Майкла Беста

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

Процитувавши Михайла:

Спочатку я запропонував використовувати beforeChangeдля вирішення цієї проблеми, але з тих пір зрозумів, що це не завжди надійно (наприклад, якщо ви звертаєтесь valueHasMutated()до спостережуваного).


3

Я виявив, що можу зателефонувати peek () із записуваного обчислюваного спостережуваного, щоб отримати попереднє значення.

Щось подібне (див. 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
На жаль, це не працює, оскільки до того часу, коли буде викликаний зворотний виклик передплати, значення вже змінилося, і тому peek()ви отримаєте нове значення.
Michael Teper

@MichaelTeper Я знаю, що я опублікував свою відповідь рік тому, але після того, як я отримав кілька проти, я щойно перевірив її, і вона працює. Див .: jsfiddle.net/4MUWp
rjmunro

Гаразд, я бачу, що ви там робили ... Питання було про отримання значення у subscribeзворотному виклику, що неможливо зробити за допомогою peek (). Ваш приклад нічого не доводить і може заплутати новачка. Ви в основному обгортаєте тут приватну змінну і відображаєте її значення перед встановленням - тому, звичайно, вона не зміниться.
Simon_Weaver
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.