refactors Discourse.debounce
This commit is contained in:
parent
aef4227073
commit
d0f3765967
|
@ -1,6 +1,7 @@
|
||||||
/**
|
/**
|
||||||
Debounce a Javascript function. This means if it's called many times in a time limit it
|
Debounce a Javascript function. This means if it's called many times in a time limit it
|
||||||
should only be executed once.
|
should only be executed once (at the end of the limit counted from the last call made).
|
||||||
|
Original function will be called with the context and arguments from the last call made.
|
||||||
|
|
||||||
@method debounce
|
@method debounce
|
||||||
@module Discourse
|
@module Discourse
|
||||||
|
@ -8,32 +9,16 @@
|
||||||
@param {Number} wait how long to wait
|
@param {Number} wait how long to wait
|
||||||
**/
|
**/
|
||||||
Discourse.debounce = function(func, wait) {
|
Discourse.debounce = function(func, wait) {
|
||||||
var timeout = null;
|
var self, args;
|
||||||
|
var later = function() {
|
||||||
|
func.apply(self, args);
|
||||||
|
};
|
||||||
|
|
||||||
return function() {
|
return function() {
|
||||||
var context = this;
|
self = this;
|
||||||
var args = arguments;
|
args = arguments;
|
||||||
|
|
||||||
var later = function() {
|
Ember.run.debounce(null, later, wait);
|
||||||
timeout = null;
|
|
||||||
return func.apply(context, args);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (timeout) return;
|
|
||||||
|
|
||||||
var currentWait;
|
|
||||||
if (typeof wait === "function") {
|
|
||||||
currentWait = wait();
|
|
||||||
} else {
|
|
||||||
currentWait = wait;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (timeout) {
|
|
||||||
clearTimeout(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout = setTimeout(later, currentWait);
|
|
||||||
return timeout;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,10 @@ var firedOnce = function(message) {
|
||||||
ok(original.calledOnce, message);
|
ok(original.calledOnce, message);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var firedTwice = function(message) {
|
||||||
|
ok(original.calledTwice, message);
|
||||||
|
};
|
||||||
|
|
||||||
var notFired = function(message) {
|
var notFired = function(message) {
|
||||||
ok(!original.called, message);
|
ok(!original.called, message);
|
||||||
};
|
};
|
||||||
|
@ -39,27 +43,20 @@ test("executes delayed function only once, no matter how many times debounced fu
|
||||||
firedOnce("second call was supressed");
|
firedOnce("second call was supressed");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("does not prolong the timeout when the debounced function is called for the second time during the timeout", function() {
|
test("prolongs the timeout when the debounced function is called for the second time during the timeout", function() {
|
||||||
debounced();
|
debounced();
|
||||||
|
|
||||||
clock.tick(50);
|
clock.tick(50);
|
||||||
debounced();
|
debounced();
|
||||||
|
|
||||||
clock.tick(50);
|
clock.tick(50);
|
||||||
firedOnce("function is executed exactly at the end of the original timeout");
|
notFired("at the end of the original timeout nothing happens");
|
||||||
});
|
|
||||||
|
|
||||||
test("returns a JS timer handle that allows delayed execution to be cancelled before the timeout ends", function() {
|
|
||||||
var timerId = debounced();
|
|
||||||
|
|
||||||
clock.tick(50);
|
clock.tick(50);
|
||||||
clearTimeout(timerId);
|
firedOnce("function is executed exactly at the end of the prolonged timeout");
|
||||||
|
|
||||||
clock.tick(50);
|
|
||||||
notFired("timeout has ended but function was not executed");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("preserves first call's context and params when executing delayed function", function() {
|
test("preserves last call's context and params when executing delayed function", function() {
|
||||||
var firstObj = {};
|
var firstObj = {};
|
||||||
var secondObj = {};
|
var secondObj = {};
|
||||||
|
|
||||||
|
@ -67,11 +64,11 @@ test("preserves first call's context and params when executing delayed function"
|
||||||
debounced.call(secondObj, "second");
|
debounced.call(secondObj, "second");
|
||||||
|
|
||||||
clock.tick(100);
|
clock.tick(100);
|
||||||
ok(original.calledOn(firstObj), "the context of the first of two subsequent calls is preserved");
|
ok(original.calledOn(secondObj), "the context of the last of two subsequent calls is preserved");
|
||||||
ok(original.calledWithExactly("first"), "param passed during the first of two subsequent calls is preserved");
|
ok(original.calledWithExactly("second"), "param passed during the last of two subsequent calls is preserved");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("can be called again (with a different context and params) after timeout passes", function() {
|
test("can be called again after timeout passes", function() {
|
||||||
var firstObj = {};
|
var firstObj = {};
|
||||||
var secondObj = {};
|
var secondObj = {};
|
||||||
|
|
||||||
|
@ -81,6 +78,5 @@ test("can be called again (with a different context and params) after timeout pa
|
||||||
debounced.call(secondObj, "second");
|
debounced.call(secondObj, "second");
|
||||||
|
|
||||||
clock.tick(100);
|
clock.tick(100);
|
||||||
ok(original.calledOn(secondObj), "function is executed with the context of the call made after the timeout has passed");
|
firedTwice();
|
||||||
ok(original.calledWithExactly("second"), "function is executed with the param passed to the call made after the timeout has passed");
|
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue