Пользовательский удлинитель дросселя в knockout.js

У меня есть наблюдаемая, которая привязана к некоторому вводу, и иногда это значение изменяется слишком быстро, так что конечный пользователь не успевает его прочитать. Поэтому я хочу ограничить скорость изменений на входе.

Но это не дроссель, потому что дроссель - это горлышко бутылки, и наблюдаемое дросселирование не меняется вообще, пока оно меняется. Я хочу иметь собственный дроссель, так что первое изменение применяется немедленно, а затем оно может измениться только после задержки (и, конечно, каждый раз после задержки показывается значение CURRENT).

До сих пор я написал собственный ограничитель restrictSpeedChange. Вот оно: http://jsfiddle.net/kasheftin/Pn9r8/4/. И это на самом деле работает для обычных наблюдаемых.

ko.extenders.restrictChangeSpeed = function(target,timeout) {
    var writeTimeoutInstance = null;
    var currentValue = target();
    var updateValueAgain = false;
    return ko.dependentObservable({
        read: target,
        write: function(value) {
            var updateValue = function(value) {
                target(value);
                if (!writeTimeoutInstance) {
                    writeTimeoutInstance = setTimeout(function() {
                        writeTimeoutInstance = null;
                        if (updateValueAgain) {
                            updateValueAgain = false;
                            updateValue(currentValue);
                        }
                    },timeout);
                }
            }
            currentValue = value;
            if (!writeTimeoutInstance)
                updateValue(currentValue);
            else
                updateValueAgain = true;
        }
    });
}

Проблема в том, что я хочу, чтобы он работал и с вычисляемыми наблюдаемыми. Для них в расширителе throttle есть переменная throttleEvaluation, эта переменная используется в методе absoluteObservable.jsvaluPossblyAsync. Но я не хочу ничего менять в основных файлах нокаута.

В моем примере http://jsfiddle.net/kasheftin/Pn9r8/4/ обычной наблюдаемой переменной является restrictChangeSpeedVar1, и она работает, как и ожидалось. Вычисляемая переменная - restrictChangeSpeedComputedVar1. Что я должен сделать, чтобы он работал как первый?

1 ответ

Решение

Быстрая мысль о существующем коде:

В вашем расширителе вы можете увидеть, имеете ли вы дело с не записываемой вычисляемой наблюдаемой, а затем вернуть наблюдаемую, которая прошла через ваш расширитель и подписалась на вычисленную.

ko.extenders.restrictChangeSpeed = function(target, timeout) {
    var writeTimeoutInstance = null;
    var currentValue = target();
    var updateValueAgain = false;
    var interceptor;

    if (ko.isComputed(target) && !ko.isWriteableObservable(target)) {
        interceptor = ko.observable().extend({ restrictChangeSpeed: timeout });
        target.subscribe(interceptor);
        return interceptor;
    }
....

Ключ в том, что вам нужно что-то пройти через логику "записи". При обычном вычислении он просто переоценил бы свою логику "чтения" и обновил бы, никогда не пройдя ваш код "записи".

Вот пример: http://jsfiddle.net/rniemeyer/GPbrR/

Кроме того, у вас была опечатка в вашей скрипке:

self.restrictChangeSpeedComputedVar1 = ko.computed(this.var1).extend({restictChangeSpeed:1000});

Вы неправильно написали свое имя расширителя (restict вместо restrict), что заставило меня почесать голову во время тестирования изменений, которые я добавил, пока я не заметил это.

Единственная интересная вещь в моих изменениях заключается в том, что теперь кто-то может потенциально писать в ваши вычисления, но он всегда будет обновляться всякий раз, когда меняются базовые вычисления, и я не понимаю, почему вы намеренно пытались писать в него.

Другие вопросы по тегам