I have an observable that's binded to some input, and sometimes it's value changes too fast, so that the end user does not have time to read it. So I want to restrict the speed of changes in input.
But it's not a throttle, because throttle is a bottle neck, and the throttled observable does not change at all while it changes. I want to have a custom throttle, so that the first change applies immediately, and then it might change only after a delay (and of course, each time after a delay it shows the CURRENT value).
So far I've written the custom restrictSpeedChange extender. Here it is: http://jsfiddle.net/kasheftin/Pn9r8/4/. And it actually works for usual observables.
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;
}
});
}
The problem is I want it to work with computed observables as well. For them throttle extender has throttleEvaluation variable, this variable is used in dependentObservable.js evaluatePossiblyAsync method. But I don't want to change anything in core knockout files.
In my example http://jsfiddle.net/kasheftin/Pn9r8/4/ usual observable variable is restrictChangeSpeedVar1 and it works as expected. Computed variable is restrictChangeSpeedComputedVar1. What should I do to make it work like the first one?
A quick thought going with your existing code:
In your extender, you could see if you are dealing with a non-writeable computed observable, then return an observable that has gone through your extender and has subscribed to the computed.
The key is that you need something to go through your "write" logic. With a normal computed, it would just re-evaluate its "read" logic and update, never going through your "write" code.
Here is a sample: http://jsfiddle.net/rniemeyer/GPbrR/
Also, you had a typo in your fiddle:
You had misspelled your extender name (
restict
instead ofrestrict
), which made me scratch my head while testing the changes that I added, until I noticed it.The only interesting thing about my changes is that now someone could potentially write to your computed, but it would always update whenever the underlying computed changed and I don't see why you would intentionally try to write to it.