hellojs-xiaotian
Version:
A clientside Javascript library for standardizing requests to OAuth2 web services (and OAuth1 - with a shim)
107 lines (92 loc) • 3.6 kB
JavaScript
ko.extenders = {
'throttle': function(target, timeout) {
// Throttling means two things:
// (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
// notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
target['throttleEvaluation'] = timeout;
// (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
// so the target cannot change value synchronously or faster than a certain rate
var writeTimeoutInstance = null;
return ko.dependentObservable({
'read': target,
'write': function(value) {
clearTimeout(writeTimeoutInstance);
writeTimeoutInstance = ko.utils.setTimeout(function() {
target(value);
}, timeout);
}
});
},
'rateLimit': function(target, options) {
var timeout, method, limitFunction;
if (typeof options == 'number') {
timeout = options;
} else {
timeout = options['timeout'];
method = options['method'];
}
// rateLimit supersedes deferred updates
target._deferUpdates = false;
limitFunction = method == 'notifyWhenChangesStop' ? debounce : throttle;
target.limit(function(callback) {
return limitFunction(callback, timeout);
});
},
'deferred': function(target, options) {
if (options !== true) {
throw new Error('The \'deferred\' extender only accepts the value \'true\', because it is not supported to turn deferral off once enabled.')
}
if (!target._deferUpdates) {
target._deferUpdates = true;
target.limit(function (callback) {
var handle;
return function () {
ko.tasks.cancel(handle);
handle = ko.tasks.schedule(callback);
target['notifySubscribers'](undefined, 'dirty');
};
});
}
},
'notify': function(target, notifyWhen) {
target["equalityComparer"] = notifyWhen == "always" ?
null : // null equalityComparer means to always notify
valuesArePrimitiveAndEqual;
}
};
var primitiveTypes = { 'undefined':1, 'boolean':1, 'number':1, 'string':1 };
function valuesArePrimitiveAndEqual(a, b) {
var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
return oldValueIsPrimitive ? (a === b) : false;
}
function throttle(callback, timeout) {
var timeoutInstance;
return function () {
if (!timeoutInstance) {
timeoutInstance = ko.utils.setTimeout(function () {
timeoutInstance = undefined;
callback();
}, timeout);
}
};
}
function debounce(callback, timeout) {
var timeoutInstance;
return function () {
clearTimeout(timeoutInstance);
timeoutInstance = ko.utils.setTimeout(callback, timeout);
};
}
function applyExtenders(requestedExtenders) {
var target = this;
if (requestedExtenders) {
ko.utils.objectForEach(requestedExtenders, function(key, value) {
var extenderHandler = ko.extenders[key];
if (typeof extenderHandler == 'function') {
target = extenderHandler(target, value) || target;
}
});
}
return target;
}
ko.exportSymbol('extenders', ko.extenders);