Пользовательский удлинитель дросселя в 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
), что заставило меня почесать голову во время тестирования изменений, которые я добавил, пока я не заметил это.
Единственная интересная вещь в моих изменениях заключается в том, что теперь кто-то может потенциально писать в ваши вычисления, но он всегда будет обновляться всякий раз, когда меняются базовые вычисления, и я не понимаю, почему вы намеренно пытались писать в него.