Understanding Throttle and Debounce Through Analogy:
###Throttle:
A lazy person who ignores your commands until he is rested.
###Debounce:
A cranky clerk condescending waiting for you to stop talking before doing anything.
####Note:
For throttle's demonstration, the task animation time is set to the same as the resting time. In most use cases, the task itself is relatively instant so there would be more than 1 dot moving around. Throttle then adjusts the minimum distance between each dot, 'throttling' the firehose of tasks to an acceptable level.
For debounce, the red timer is usually very short. The main purpose is to group multiple actions into 1 action such as accidentally double clicking a save button.
Both actions can be hacked to do the work of the other though it's best to keep the proper model in mind. Throttle 'throttles' the rate of actions while debounce 'throttles' noise so that random noise is not perceived as multiple actions.
xxxxxxxxxx
<meta charset="utf-8">
<style>
.throttle-button, .debounce-button {
cursor: pointer
}
text {
-webkit-user-select: none
}
circle {
fill: #416EE9;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<div id="throttle-area">
<svg></svg>
</div>
<div id="debounce-area">
<svg></svg>
</div>
<script>
var margin = {top: 30, right: 40, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//var svg = d3.select("body").append("svg")
var throttle = d3.select("#throttle-area svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height/4 + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.append('g');
throttle.append('rect')
.attr('width', 600)
.attr('height', 100)
.attr('fill', "#eee");
var restPeriod = 3000;
//button
throttle.append('text').text("throttle")
.attr('class', 'throttle-button')
.attr('x', 700)
.attr('y', 50)
.on('click', simpleThrottle(runThrottle,restPeriod));
var throttleCircleGroup = throttle.append('g').attr('class', 'circleGroup')
var throttleText = throttleCircleGroup.append('text')
.attr('y', 20)
.attr('opacity', 0);
var throttleCircle = throttleCircleGroup.append('circle')
.attr('cx', 20)
.attr('cy', 45)
.attr('r', 10);
function runThrottle(){
throttleCircleGroup.transition().duration(restPeriod/2)
.attr('transform', "translate(550,0)")
.transition().duration(restPeriod/2)
.attr('transform', "translate(0,0)")
}
function simpleThrottle(fn, restPeriod){
var free = true;
return function(){
if (free){
fn.apply(this, arguments);
flashText("I'm going!");
free = false;
setTimeout(function(){
free = true;
}, restPeriod)
} else {
flashText("I'm tired T.T");
}
}
}
function flashText(text) {
throttleText.text(text)
.attr('opacity', 1)
.transition().duration(200)
.attr('opacity', 0);
}
var debounce = d3.select("#debounce-area svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height/4 + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.append('g').attr('class', 'debounce');
debounce.append('rect')
.attr('width', 600)
.attr('height', 100)
.attr('fill', "#eee");
var waitPeriod = 1000;
//button
debounce.append('text').text('debounce')
.attr('class', 'debounce-button')
.attr('x', 700)
.attr('y', 50)
.on('click', simpleDebounce(runDebounce,waitPeriod));
var debounceCircleGroup = debounce.append('g');
debounceCircleGroup.append('circle')
.attr('r', 10)
.attr('cx', 20)
.attr('cy', 45);
var debounceText = debounceCircleGroup
.append('text')
.attr("y", 20)
.text("Are you done yet?")
.attr('opacity', 0);
function runDebounce(){
debounceCircleGroup.transition().duration(100)
.attr('transform', "translate(550,0)")
.transition().duration(100)
.attr('transform', "translate(0,0)")
}
function simpleDebounce(fn, waitPeriod){
var timeout;
return function(){
clearTimeout(timeout);
debounce.append('rect').attr('class', 'timer')
.attr('x', 0)
.attr('y', -5)
.attr('width', 600)
.attr('height', 5)
.attr('fill', "#e00")
.transition().duration(waitPeriod)
.attr('width', 0);
debounceText.attr('opacity', 1)
.transition().duration(100)
.attr('opacity', 0);
timeout = setTimeout(fn,waitPeriod);
}
}
</script>
https://d3js.org/d3.v3.min.js
https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js