Difference Between throttling and debouncing a function - javascript

Can anyone give me a in-simple-words explanation about the difference between throttling and debouncing a function for rate-limiting purposes.
To me both seems to do the same the thing. I have checked these two blogs to find out :
http://remysharp.com/2010/07/21/throttling-function-calls
http://benalman.com/projects/jquery-throttle-debounce-plugin/

To put it in simple terms:
Throttling will delay executing a function. It will reduce the notifications of an event that fires multiple times.
Debouncing will bunch a series of sequential calls to a function into a single call to that function. It ensures that one notification is made for an event that fires multiple times.
You can visually see the difference here
If you have a function that gets called a lot - for example when a resize or mouse move event occurs, it can be called a lot of times. If you don't want this behaviour, you can Throttle it so that the function is called at regular intervals. Debouncing will mean it is called at the end (or start) of a bunch of events.

Personally I found debounce harder to comprehend than throttle.
As both functions help you postpone and reduce the rate of some execution. Assuming you are calling decorated functions returned by throttle/debounce repeatedly...
Throttle: the original function will be called at most once per specified period.
Debounce: the original function will be called after the caller stops calling the decorated function after a specified period.
I found the last part of debounce crucial to understand the goal it's trying to achieve. I also found an old version of the implementation of _.debounce helps the understanding (courtesy of https://davidwalsh.name/function-debounce).
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
A far-fetched metaphor, but maybe could also help.
You have a friend named Chatty who likes to talk with you via IM. Assuming when she talks she sends a new message every 5 seconds, while your IM application icon is bouncing up and down, you can take the...
Naive approach: check every message as long as it arrives. When your app icon bounces, check. It's not the most effective way, but you are always up-to-date.
Throttle approach: you check once every 5 minutes (when there are new ones). When new message arrives, if you have checked anytime in the last 5 minutes, ignore it. You save your time with this approach, while still in the loop.
Debounce approach: you know Chatty, she breaks down a whole story into pieces, sends them in one message after another. You wait until Chatty finishes the whole story: if she stops sending messages for 5 minutes, you would assume she has finished, now you check all.

Differences
+--------------+-------------------+-------------------+
| | Throttle 1 sec | Debounce 1 sec |
+--------------+-------------------+-------------------+
| Delay | no delay | 1 sec delay |
| | | |
| Emits new if | last was emitted | there is no input |
| | before 1 sec | in last 1 sec |
+--------------+-------------------+-------------------+
Explanation by use case:
Search bar- Don't want to search every time user presses key? Want to search when user stopped typing for 1 sec. Use debounce 1
sec on key press.
Shooting game- Pistol take 1 sec time between each shot but user click mouse multiple times. Use throttle on mouse click.
Reversing their roles:
Throttling 1 sec on search bar- If users types abcdefghij with every character in 0.6 sec. Then throttle will trigger at first a press. It will will ignore every press for next 1 sec i.e. bat .6 sec will be ignored. Then c at 1.2 sec will again trigger, which resets the time again. So d will be ignored and e will get triggered.
Debouncing pistol for 1 sec- When user sees an enemy, he clicks mouse, but it will not shoot. He will click again several times in that sec but it will not shoot. He will see if it still has bullets, at that time (1 sec after last click) pistol will fire automatically.
Further explanation for input-output comparision with real life
There are some guards outside a bar. Guard allows person who say "I will go" to let inside the bar. That is a normal scenario. Anyone saying "I will go" is allowed to go inside the bar.
Now there is a Throttle Guard (throttle 5 sec). He likes people who responds first. Anyone who says "I will go" first, he allows that person. Then he rejects every person for 5 sec. After that, again anyone saying it first will be allowed and others will be rejected for 5 sec.
There is another Debounce Guard (debounce 5 sec). He likes people who brings mental rest to him for 5 seconds. So if any person says "I will go", the guard wait for 5 seconds. If no other person disturbs him for 5 seconds, he allow the first person. If some other person says "I will go" in those 5 sec, he reject the first one. He again starts the 5 sec waiting for the second person to see if the second one can bring him the mental rest.

Throttle (1 sec): Hello, I am a robot. As long as you keep pinging me, I will keep talking to you, but after exactly 1 second each. If you ping me for a reply before a second is elapsed, I will still reply to you at exactly 1 second interval. In other words, I just love to reply at exact intervals.
Debounce (1 sec): Hi, I am that ^^ robot's cousin. As long as you keep pinging me, I am going to remain silent because I like to reply only after 1 second is passed since the last time you pinged me. I don't know, if it is because I have an attitude problem or because I just don't like to interrupt people. In other words, if you keep asking me for replies before 1 second is elapsed since your last invocation, you will never get a reply. Yeah yeah...go ahead! call me rude.
Throttle (10 min): I am a logging machine. I send system logs to our backend server, after a regular interval of 10 minutes.
Debounce (10 sec): Hi, I am not cousin of that logging machine. (Not every debouncer is related to a throttler in this imaginary world). I work as a waiter in a nearby restaurant. I should let you know that as long as you keep adding stuff to your order, I will not go to the kitchen for execution of your order. Only when 10 seconds have elapsed after you last modified your order, I will assume that you are done with your order. Only then will I go and execute your order in the kitchen.
Cool Demos: https://css-tricks.com/debouncing-throttling-explained-examples/
Credits for the waiter analogy: https://codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf

Throttling enforces a maximum number of times a function can be called over time. As in "execute this function at most once every 100 milliseconds."
Debouncing enforces that a function not be called again until a certain amount of time has passed without it being called. As in "execute this function only if 100 milliseconds have passed without it being called."
ref

It's simpler than the demos.
They do the exact same thing (rate limiting) but while throttle is being called it fires your function periodically, while debounce just fires once at the end.
Throttle fires throughout, debounce only fires at the end.
Example: If you're scrolling, throttle will slowly call your function while you scroll (every X milliseconds). Debounce will wait until after you're done scrolling to call your function.
--
I like to think of throttle as "including debounce", they both make a final call after the events are done, but due to implementation details, the two don't always make this final call at the exact same time, which can make demos confusing.

In layman's terms:
Debouncing will prevent a function from running while it is still being called frequently. A debounced function will only run after it has been determined that it is no longer being called, at which point it will run exactly once. Practical examples of debouncing:
Auto-saving or validating the contents of a text-field if the user "stopped typing": the operation will only be done once, AFTER it has been determined that the user is no longer typing (no longer pressing keys).
Logging where users rest their mouse: the user is no longer moving their mouse, so the (last) position can be logged.
Throttling will simply prevent a function from running if it has run recently, regardless of the call frequency. Practical examples of throttling:
Implementations of v-sync are based on throttling: the screen will only be drawn if 16ms elapsed since the last screen draw. No matter how many times the screen refresh functionality is called, it will only run at most once every 16ms.

A real-life analogy that personally helps me remember:
debounce = a conversation. you wait for the other person to finish speaking before you reply.
throttle = a drum bit. you only play notes on a simple 4/4 drum bit.
Use cases for debounce:
Typing. You want to do something after the user stopped typing. So waiting 1sec after the last keystroke makes sense. Each keystroke restarts the wait.
Animation. You want to shrink back an element after the user stopped hovering over it. Not using debounce might cause an erratic animation as a result of the cursor unintentionally moving between the "hot" and "cold" zones.
Use cases for throttle:
Scrolling. You want to react to scrolling but limit the amount of calculations made, so doing something every 100ms is enough to prevent potential lag.
Mouse move. Same as scrolling but for mouse move.
API calls You want to fire an API call on certain UI events but want to limit the number of API calls you make not to overload your server.

Debouncing allows you to manage the frequency of calls that a function can receives. It combines multiple calls that happen on a given function so that repeated calls that occur before the expiration of a specific time duration are ignored. Basically debouncing ensures that exactly one signal is sent for an event that may be happening several times.
Throttling restricts the frequency of calls that a function receives to a fixed time interval. It is used to ensuring that the target function is not invoked more often than the specified delay. Throttling is the reduction in rate of a repeating event.

A picture is worth a thousand words
Throttle
Debounce
Notice the Debounce will not fire until the events flow stops. However, Throttle will fire an event each interval.
(Thanks to css-tricks)

Throttling
Throttling enforces a maximum number of times a function can be called
overtime. As in "execute this function at most once every 100
milliseconds." Say under normal circumstances you would call this
function 1,000 times over 10 seconds. If you throttle it to only once
per 100 milliseconds, it would only execute that function at most 100
times
(10s * 1,000) = 10,000ms
10,000ms / 100ms throttling = 100 maximum calls
Debouncing
Debouncing enforces that a function not be called again until a
certain amount of time has passed without it being called. As in
"execute this function only if 100 milliseconds have passed without it
being called."
Perhaps a function is called 1,000 times in a quick burst, dispersed over 3 seconds, then stops being called. If you have debounced it at 100 milliseconds, the function will only fire once, at 3.1 seconds, once the burst is over. Each time the function is called during the burst it resets the debouncing timer
source:- throttle and debouncing

Putting debounce and throttle together can be very confusing, because they both share a parameter called delay.
Debounce. The delay is to wait till there's no more invokes anymore, then to invoke it. Very much like to close an elevator door: the door has to wait till no one tries to get in before closing.
Throttle. The delay is to wait with a frequency, then invokes for the last one. Very much like to fire a pistol gun, the gun just can't be fired beyond certain rate.
Let's take a look at the implementation to see in details.
function debounce(fn, delay) {
let handle = null
return function () {
if (handle) {
handle = clearTimeout(handle)
}
handle = setTimeout(() => {
fn(...arguments)
}, delay)
}
}
Debounce, keeps interrupting the timeout until no more interruptions, and then fires fn.
function throttle(fn, delay) {
let handle = null
let prevArgs = undefined
return function() {
prevArgs = arguments
if (!handle) {
fn(...prevArgs)
prevArgs = null
handle = setInterval(() => {
if (!prevArgs) {
handle = clearInterval(handle)
} else {
fn(...prevArgs)
prevArgs = null
}
}, delay)
}
}
}
Throttle, stores the last call arguments, and sets up an interval to fire until no past fires any more.
Similarities. They both have a delay time, and there's no fire during the delay, especially when there's only one fire. Both do not aggregate past events, so the number of events can be different than the actual fires.
Difference. The delay can be extended in debounce case with repeated events. Whereas the delay in the throttle case is fixed. So in general you get more fires from the throttle than debounce.
Easy to remember. Debounce groups bundle calls into one. Throttle keeps bundle calls within certain frequency.
Updated 1-20-23
Throttle might not need setInterval, here's a new version I wrote recently which takes care of this as well.
function throttle(fn, delay) {
let canFire = true
let queue = []
function pop() {
if (queue.length < 1) return
const [that, args] = queue.pop()
fn.apply(that, args)
canFire = false
setTimeout(() => {
canFire = true
pop()
}, delay)
}
function push() {
queue.push([this, arguments])
if (canFire) pop()
}
push.cancel = () => {
queue = []
}
return push
}

throtle is just a wrapper around debounce which makes debounce to call passed function in some period of time, if debounce delays a function call on period of time which is bigger then specified in throtle.

Suppose we have a callback function "cb" to be called on event "E".
Let "E" getting triggered 1000 times in 1 second, hence there would be 1000 calls to "cb". That is 1 call/ms. To optimize we can either use:
Throttling: With throttling of (100ms), "cb" would be
called on [100th ms, 200th ms, 300th ms, ... 1000th ms]. That is 1 call/100 ms. Here 1000 calls to "cb" optimized to 10 calls.
Debouncing: With debouncing of (100ms), "cb" would be called only once on [1100th sec]. That is 100ms after the last trigger of "E" which happend on [1000th ms]. Here 1000 calls to "cb" optimized to 1 call.

the lodash Library suggests the following article https://css-tricks.com/debouncing-throttling-explained-examples/ which detailed explain the difference between Debounce and Throttle and their origination

Debouncing and Throttling are ways to select targets from a serial of events for the purpose of reduction. Both of they need a period of time as an argument, for example: x ms, and trailing / leading variety to define how to select.
Debouncing
Select an event when no other event occurs in next x ms
"--->": timeline "o,e": events "|===|": period (x=5)
--oo-e-----ooo-e----o-oo--oe-----o-o-ooe------> events
|===| |===| |===| |===|
||===| ||===| | |===| | |===|
| |===| | |===| | |===| | |===|
| | | |===|| |===| | |===|
| | | || |===| | |===|
---------e---------e-----------e-----------e--> selected events (trailing)
--o--------o--------o------------o------------> selected events (leading)
Throttling
Select an event in every x ms when an event occurs
"--->": timeline "o,e": events "|===|": period (x=5)
--oo-e-----ooo-e----o-oe--oe-----o-o-eoe------> events
|===| |===| |===| |===| |===||===|
------e--------e--------e-----e------e----e---> selected events (trailing)
--o--------o--------o-----o------o----o-------> selected events (leading)

Debouncing makes it so a function can only be executed after a certain amount of time since it was last invoked
function debounce(func,wait){
let timeout
return(...arg) =>{
clearTimeout(timeout);
timeout= setTimeout(()=>func.apply(this,arg),wait)
}
}
function SayHello(){
console.log("Jesus is saying hello!!")
}
let x = debounce(SayHello,3000)
x()
The throttle pattern limits the maximum number of times a given event handler can be called over time. It lets the handler be called periodically, at specified intervals, ignoring every call that occurs before this wait period is over.
function throttle(callback, interval) {
let enableCall = true;
return (...args)=> {
if (!enableCall) return;
enableCall = false;
callback.apply(this, args);
setTimeout(() => enableCall = true, interval);
}
}
function helloFromThrottle(){
console.log("Jesus is saying hi!!!")
}
const foo = throttle(helloFromThrottle,5000)
foo()

As far as I understand, in simple terms
Throttling - similar to calling setInterval(callback) for certain number of times i.e calling same function for certain number of times over time on occurrence of event
and..
Debouncing - similar to calling setTImeout(callbackForApi) or calling a function after certain time has passed on occurrence of event.
This link can be helpful-
https://css-tricks.com/the-difference-between-throttling-and-debouncing/

For examples of typical uses cases, I recommend #Guy's answer. But the best way for me to understand these two concepts was to make it about pizzas. 🍕
Let's say you're an amazing pizza-maker, and so customers are in your shop constantly demanding more pizzas.
Throttling:
You decide you will only put out one pizza at the end of every hour, as long you received at least one request for pizza during that hour.
You receive 100 requests for pizzas in one hour, so you provide a pizza at the end of that hour. Then, you get no requests for pizza the next hour, so you don't put out a pizza. Then you get 10 requests for pizzas the next hour, and so you put out a pizza at the end of that hour.
Debouncing:
You are getting annoyed about your customers constantly demanding pizzas, and so you decide you will only give them a pizza after they have stopped asking you for a full minute.
They demand pizzas for 30 minutes straight, but then they stop asking for a minute after that. At that point, you will give them one pizza.
Then they demand pizzas for 5 minutes straight, and stop asking for a minute after that. At that point, you give them another pizza.

it’s in fact the way of limiting an event. For example, if you are listening on an event onclick, if it’s regular it will listen to every click you made.
If you use Throttle, it will set an interval between the time you want to listen to event for example listen to one click every second.
Debounce is a more restrictive one, it will only fire itself at the beginning or the ending of an event. For example, you are scrolling and you use Debounce, it will trigger only when you start and you finish to scroll.

Debounce:
Executes the function after the interval if function isn't being called within that interval.
Throttle:
Executes the function n times at fixed interval.

How debouncing works in hardware.
Debouncing is the process of removing noise from a digital signal. When a button is pressed, the signal bouncing around can cause the button to be registered as being pressed multiple times. Debouncing removes this noise so that the button is only registered as being pressed once. Picture a ruler being bounced on the edge of a desk, and imagine metal contacts inside a switch bouncing like this.
Better still, look at this diagram, showing the switch noise caused by bouncing.
We use resistors and capacitors of properly calculated ratings to smooth out the signal for n ms.
Explain how signal throttling works in hardware.
Signal throttling is the process of limiting the number of times a signal can be registered. This is often used to prevent a button from being registered as being pressed multiple times in a short period of time.
I prefer the term gating, but that's because I'm into electronic music production.
We open the gate at the end of each throttle period, and allow the signal to pass, and then close the gate again, for the next throttle period.
Explain how debouncing works in software.
Debouncing in software is often accomplished by using a timer. When the button is pressed, the timer is started. If the button is pressed again before the timer expires, the timer is reset. This ensures that the button can only be registered as being pressed once per debounce period.
In many implementations of debounce, we create a debounced version of the function which is embedded in a closure containing a timer (or gate). When the timer delay expires we set it it null again. The actual function only runs when the timer is null. Usually, this means when we first call the debounced function, it'll run once, then subsequent calls to it will be effectively cancelled until the delay time has elapsed.
In some implementations of debounce, while a stream of calls are fired and the timer hasn't expired, the timer will be restarted. Only calling the function after the bouncing has stopped. This is usually called a trailing debounce.
Explain how throttling works in software.
Throttling in software is often accomplished by using a counter. When the button is pressed, the counter is incremented. If the button is pressed again before the counter reaches a certain threshold, the counter is reset. This limits the number of times the button can be registered as being pressed in a given period of time. It's good to visualise this as a pulse or beat, which opens and closes a gate while calls are being sent to the throttle.
Rate limiting is another way to think of a throttle.
Why is this such a common cause of confusion?
In many many use cases a debounce or throttle will get you the results you want, especially if the software implementation you're using allows you to chain, trail, or lead your throttle / debounce.
Still, I hope all the answers here and this one have helped you understand more clearly.
They're very similar.

This article explains it rather well and has graphics too.
https://css-tricks.com/debouncing-throttling-explained-examples/
From the article (and with some clarifications):
The main difference between this (throttle) and debouncing is that throttle guarantees the execution of the function regularly, at least every X milliseconds.
Normally debounce calls the function at the end of a specified time and throttle calls when the first call to the throttled function is made. Sometimes debounce can take extra config that changes this to do the call at the beginning instead. Some implemenations of debounce can actually do what throttle does (see Lodash source code) when called with specific configs.

Simple concept for throttle is clicking the submit button frequently in a form, we need to use throttle. So the submit function is prevent from frequent clicks. It saves the same requests pass into the function.
And about debounce, write a simple code with input text tag for searching some data from the server. oninput, you use the debounce so it removes the previous requests and pass the last typed word to the server
const throttle = (callback, time = 0) => {
let throttle_req, count = 0;
return async function () {
var context = this, args = arguments;
if(throttle_req) return;
throttle_req = true;
if(time > 0)
{
callback.apply(context, args);
setTimeout(() => {
throttle_req = false;
}, time || 200)
}
else
{
let response = await callback.apply(context, args);
throttle_req = false;
return response;
}
}
}
const debounce = (callback, time = 0) => {
let debounce_req;
return function () {
var context = this, args = arguments;
clearTimeout(debounce_req)
debounce_req = setTimeout(() => {
debounce_req = null;
callback.apply(context, args);
}, time || 200)
}
}
How we call: Just wrap your function with throttle or debounce to check the difference
Throttle ex: same button click more than 1 time
var throttleFunct = throttle(function(num) {
console.log(num, "hello throttle")
}, 2000);
throttleFunct(300) //it execute. because its the first call
throttleFunct(400) //it won't execute
throttle async without time
var getDataAsync = throttle(function(id, name) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({name: name, id: id})
}, 2000)
})
});
async function test() {
let response = await getDataAsync(120, 'Sherley').then(resp => resp)
console.log(response, "respond") //it execute. because its the first call
response = await getDataAsync(120, 'James').then(resp => resp)
console.log(response, "respond2")//it executes 2 after first request
response = await getDataAsync(120, 'Jonathan').then(resp => resp)
console.log(response, "respond3")//it executes 3 after second request
}
test()
Debounce For ex: search box autocomplete
var debounceFunct = debounce(function(num) {
console.log(num+1)
}, 2000);
debounceFunct(300) //it won't execute and it cancelled
debounceFunct(400) // it executes and it replaced with the previous call. because this is the latest event fire

The major difference between debouncing and throttling is that debounce calls a function when a user hasn't carried out an event in a specific amount of time, while throttle calls a function at intervals of a specified amount of time while the user is carrying out an event.

What really matters here, in most simple terms: if you have some action, that is continuously repeated for some period (such as mouse movement, or page resize events), and you need to run some function in response, but you don't want to react to every action (cause it may detriment the performance), you have 2 options:
debounce - you skip all incoming actions, except the last one (the 'last one' is defined by the 'wait' time period you set for debounce function, for example, 2s - it will consider that actions flood stopped, if no actions were taken for 2s, and then it will react. This strategy is reasonable if you don't care about regular updates, you just need to react at least once.
throttle - if you want to react 'on schedule', to make regular updates even if actions flood is endless, you make your function run at regular intervals (no more often, then the specified time interval), for example 2s throttling will mean that your response will be executed an once if action is taken, but no less then 2s after that. So with continuous actions flood your response will be run on 0s, 2s, 4s, 6s, 8s...

Related

The debounce method from underscore library isn't working as expected, how do I create a function that can only be called once a second? [duplicate]

Can anyone give me a in-simple-words explanation about the difference between throttling and debouncing a function for rate-limiting purposes.
To me both seems to do the same the thing. I have checked these two blogs to find out :
http://remysharp.com/2010/07/21/throttling-function-calls
http://benalman.com/projects/jquery-throttle-debounce-plugin/
To put it in simple terms:
Throttling will delay executing a function. It will reduce the notifications of an event that fires multiple times.
Debouncing will bunch a series of sequential calls to a function into a single call to that function. It ensures that one notification is made for an event that fires multiple times.
You can visually see the difference here
If you have a function that gets called a lot - for example when a resize or mouse move event occurs, it can be called a lot of times. If you don't want this behaviour, you can Throttle it so that the function is called at regular intervals. Debouncing will mean it is called at the end (or start) of a bunch of events.
Personally I found debounce harder to comprehend than throttle.
As both functions help you postpone and reduce the rate of some execution. Assuming you are calling decorated functions returned by throttle/debounce repeatedly...
Throttle: the original function will be called at most once per specified period.
Debounce: the original function will be called after the caller stops calling the decorated function after a specified period.
I found the last part of debounce crucial to understand the goal it's trying to achieve. I also found an old version of the implementation of _.debounce helps the understanding (courtesy of https://davidwalsh.name/function-debounce).
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
A far-fetched metaphor, but maybe could also help.
You have a friend named Chatty who likes to talk with you via IM. Assuming when she talks she sends a new message every 5 seconds, while your IM application icon is bouncing up and down, you can take the...
Naive approach: check every message as long as it arrives. When your app icon bounces, check. It's not the most effective way, but you are always up-to-date.
Throttle approach: you check once every 5 minutes (when there are new ones). When new message arrives, if you have checked anytime in the last 5 minutes, ignore it. You save your time with this approach, while still in the loop.
Debounce approach: you know Chatty, she breaks down a whole story into pieces, sends them in one message after another. You wait until Chatty finishes the whole story: if she stops sending messages for 5 minutes, you would assume she has finished, now you check all.
Differences
+--------------+-------------------+-------------------+
| | Throttle 1 sec | Debounce 1 sec |
+--------------+-------------------+-------------------+
| Delay | no delay | 1 sec delay |
| | | |
| Emits new if | last was emitted | there is no input |
| | before 1 sec | in last 1 sec |
+--------------+-------------------+-------------------+
Explanation by use case:
Search bar- Don't want to search every time user presses key? Want to search when user stopped typing for 1 sec. Use debounce 1
sec on key press.
Shooting game- Pistol take 1 sec time between each shot but user click mouse multiple times. Use throttle on mouse click.
Reversing their roles:
Throttling 1 sec on search bar- If users types abcdefghij with every character in 0.6 sec. Then throttle will trigger at first a press. It will will ignore every press for next 1 sec i.e. bat .6 sec will be ignored. Then c at 1.2 sec will again trigger, which resets the time again. So d will be ignored and e will get triggered.
Debouncing pistol for 1 sec- When user sees an enemy, he clicks mouse, but it will not shoot. He will click again several times in that sec but it will not shoot. He will see if it still has bullets, at that time (1 sec after last click) pistol will fire automatically.
Further explanation for input-output comparision with real life
There are some guards outside a bar. Guard allows person who say "I will go" to let inside the bar. That is a normal scenario. Anyone saying "I will go" is allowed to go inside the bar.
Now there is a Throttle Guard (throttle 5 sec). He likes people who responds first. Anyone who says "I will go" first, he allows that person. Then he rejects every person for 5 sec. After that, again anyone saying it first will be allowed and others will be rejected for 5 sec.
There is another Debounce Guard (debounce 5 sec). He likes people who brings mental rest to him for 5 seconds. So if any person says "I will go", the guard wait for 5 seconds. If no other person disturbs him for 5 seconds, he allow the first person. If some other person says "I will go" in those 5 sec, he reject the first one. He again starts the 5 sec waiting for the second person to see if the second one can bring him the mental rest.
Throttle (1 sec): Hello, I am a robot. As long as you keep pinging me, I will keep talking to you, but after exactly 1 second each. If you ping me for a reply before a second is elapsed, I will still reply to you at exactly 1 second interval. In other words, I just love to reply at exact intervals.
Debounce (1 sec): Hi, I am that ^^ robot's cousin. As long as you keep pinging me, I am going to remain silent because I like to reply only after 1 second is passed since the last time you pinged me. I don't know, if it is because I have an attitude problem or because I just don't like to interrupt people. In other words, if you keep asking me for replies before 1 second is elapsed since your last invocation, you will never get a reply. Yeah yeah...go ahead! call me rude.
Throttle (10 min): I am a logging machine. I send system logs to our backend server, after a regular interval of 10 minutes.
Debounce (10 sec): Hi, I am not cousin of that logging machine. (Not every debouncer is related to a throttler in this imaginary world). I work as a waiter in a nearby restaurant. I should let you know that as long as you keep adding stuff to your order, I will not go to the kitchen for execution of your order. Only when 10 seconds have elapsed after you last modified your order, I will assume that you are done with your order. Only then will I go and execute your order in the kitchen.
Cool Demos: https://css-tricks.com/debouncing-throttling-explained-examples/
Credits for the waiter analogy: https://codeburst.io/throttling-and-debouncing-in-javascript-b01cad5c8edf
Throttling enforces a maximum number of times a function can be called over time. As in "execute this function at most once every 100 milliseconds."
Debouncing enforces that a function not be called again until a certain amount of time has passed without it being called. As in "execute this function only if 100 milliseconds have passed without it being called."
ref
In layman's terms:
Debouncing will prevent a function from running while it is still being called frequently. A debounced function will only run after it has been determined that it is no longer being called, at which point it will run exactly once. Practical examples of debouncing:
Auto-saving or validating the contents of a text-field if the user "stopped typing": the operation will only be done once, AFTER it has been determined that the user is no longer typing (no longer pressing keys).
Logging where users rest their mouse: the user is no longer moving their mouse, so the (last) position can be logged.
Throttling will simply prevent a function from running if it has run recently, regardless of the call frequency. Practical examples of throttling:
Implementations of v-sync are based on throttling: the screen will only be drawn if 16ms elapsed since the last screen draw. No matter how many times the screen refresh functionality is called, it will only run at most once every 16ms.
It's simpler than the demos.
They do the exact same thing (rate limiting) but while throttle is being called it fires your function periodically, while debounce just fires once at the end.
Throttle fires throughout, debounce only fires at the end.
Example: If you're scrolling, throttle will slowly call your function while you scroll (every X milliseconds). Debounce will wait until after you're done scrolling to call your function.
--
I like to think of throttle as "including debounce", they both make a final call after the events are done, but due to implementation details, the two don't always make this final call at the exact same time, which can make demos confusing.
A real-life analogy that personally helps me remember:
debounce = a conversation. you wait for the other person to finish speaking before you reply.
throttle = a drum bit. you only play notes on a simple 4/4 drum bit.
Use cases for debounce:
Typing. You want to do something after the user stopped typing. So waiting 1sec after the last keystroke makes sense. Each keystroke restarts the wait.
Animation. You want to shrink back an element after the user stopped hovering over it. Not using debounce might cause an erratic animation as a result of the cursor unintentionally moving between the "hot" and "cold" zones.
Use cases for throttle:
Scrolling. You want to react to scrolling but limit the amount of calculations made, so doing something every 100ms is enough to prevent potential lag.
Mouse move. Same as scrolling but for mouse move.
API calls You want to fire an API call on certain UI events but want to limit the number of API calls you make not to overload your server.
Debouncing allows you to manage the frequency of calls that a function can receives. It combines multiple calls that happen on a given function so that repeated calls that occur before the expiration of a specific time duration are ignored. Basically debouncing ensures that exactly one signal is sent for an event that may be happening several times.
Throttling restricts the frequency of calls that a function receives to a fixed time interval. It is used to ensuring that the target function is not invoked more often than the specified delay. Throttling is the reduction in rate of a repeating event.
A picture is worth a thousand words
Throttle
Debounce
Notice the Debounce will not fire until the events flow stops. However, Throttle will fire an event each interval.
(Thanks to css-tricks)
Throttling
Throttling enforces a maximum number of times a function can be called
overtime. As in "execute this function at most once every 100
milliseconds." Say under normal circumstances you would call this
function 1,000 times over 10 seconds. If you throttle it to only once
per 100 milliseconds, it would only execute that function at most 100
times
(10s * 1,000) = 10,000ms
10,000ms / 100ms throttling = 100 maximum calls
Debouncing
Debouncing enforces that a function not be called again until a
certain amount of time has passed without it being called. As in
"execute this function only if 100 milliseconds have passed without it
being called."
Perhaps a function is called 1,000 times in a quick burst, dispersed over 3 seconds, then stops being called. If you have debounced it at 100 milliseconds, the function will only fire once, at 3.1 seconds, once the burst is over. Each time the function is called during the burst it resets the debouncing timer
source:- throttle and debouncing
Putting debounce and throttle together can be very confusing, because they both share a parameter called delay.
Debounce. The delay is to wait till there's no more invokes anymore, then to invoke it. Very much like to close an elevator door: the door has to wait till no one tries to get in before closing.
Throttle. The delay is to wait with a frequency, then invokes for the last one. Very much like to fire a pistol gun, the gun just can't be fired beyond certain rate.
Let's take a look at the implementation to see in details.
function debounce(fn, delay) {
let handle = null
return function () {
if (handle) {
handle = clearTimeout(handle)
}
handle = setTimeout(() => {
fn(...arguments)
}, delay)
}
}
Debounce, keeps interrupting the timeout until no more interruptions, and then fires fn.
function throttle(fn, delay) {
let handle = null
let prevArgs = undefined
return function() {
prevArgs = arguments
if (!handle) {
fn(...prevArgs)
prevArgs = null
handle = setInterval(() => {
if (!prevArgs) {
handle = clearInterval(handle)
} else {
fn(...prevArgs)
prevArgs = null
}
}, delay)
}
}
}
Throttle, stores the last call arguments, and sets up an interval to fire until no past fires any more.
Similarities. They both have a delay time, and there's no fire during the delay, especially when there's only one fire. Both do not aggregate past events, so the number of events can be different than the actual fires.
Difference. The delay can be extended in debounce case with repeated events. Whereas the delay in the throttle case is fixed. So in general you get more fires from the throttle than debounce.
Easy to remember. Debounce groups bundle calls into one. Throttle keeps bundle calls within certain frequency.
Updated 1-20-23
Throttle might not need setInterval, here's a new version I wrote recently which takes care of this as well.
function throttle(fn, delay) {
let canFire = true
let queue = []
function pop() {
if (queue.length < 1) return
const [that, args] = queue.pop()
fn.apply(that, args)
canFire = false
setTimeout(() => {
canFire = true
pop()
}, delay)
}
function push() {
queue.push([this, arguments])
if (canFire) pop()
}
push.cancel = () => {
queue = []
}
return push
}
throtle is just a wrapper around debounce which makes debounce to call passed function in some period of time, if debounce delays a function call on period of time which is bigger then specified in throtle.
Suppose we have a callback function "cb" to be called on event "E".
Let "E" getting triggered 1000 times in 1 second, hence there would be 1000 calls to "cb". That is 1 call/ms. To optimize we can either use:
Throttling: With throttling of (100ms), "cb" would be
called on [100th ms, 200th ms, 300th ms, ... 1000th ms]. That is 1 call/100 ms. Here 1000 calls to "cb" optimized to 10 calls.
Debouncing: With debouncing of (100ms), "cb" would be called only once on [1100th sec]. That is 100ms after the last trigger of "E" which happend on [1000th ms]. Here 1000 calls to "cb" optimized to 1 call.
the lodash Library suggests the following article https://css-tricks.com/debouncing-throttling-explained-examples/ which detailed explain the difference between Debounce and Throttle and their origination
Debouncing and Throttling are ways to select targets from a serial of events for the purpose of reduction. Both of they need a period of time as an argument, for example: x ms, and trailing / leading variety to define how to select.
Debouncing
Select an event when no other event occurs in next x ms
"--->": timeline "o,e": events "|===|": period (x=5)
--oo-e-----ooo-e----o-oo--oe-----o-o-ooe------> events
|===| |===| |===| |===|
||===| ||===| | |===| | |===|
| |===| | |===| | |===| | |===|
| | | |===|| |===| | |===|
| | | || |===| | |===|
---------e---------e-----------e-----------e--> selected events (trailing)
--o--------o--------o------------o------------> selected events (leading)
Throttling
Select an event in every x ms when an event occurs
"--->": timeline "o,e": events "|===|": period (x=5)
--oo-e-----ooo-e----o-oe--oe-----o-o-eoe------> events
|===| |===| |===| |===| |===||===|
------e--------e--------e-----e------e----e---> selected events (trailing)
--o--------o--------o-----o------o----o-------> selected events (leading)
Debouncing makes it so a function can only be executed after a certain amount of time since it was last invoked
function debounce(func,wait){
let timeout
return(...arg) =>{
clearTimeout(timeout);
timeout= setTimeout(()=>func.apply(this,arg),wait)
}
}
function SayHello(){
console.log("Jesus is saying hello!!")
}
let x = debounce(SayHello,3000)
x()
The throttle pattern limits the maximum number of times a given event handler can be called over time. It lets the handler be called periodically, at specified intervals, ignoring every call that occurs before this wait period is over.
function throttle(callback, interval) {
let enableCall = true;
return (...args)=> {
if (!enableCall) return;
enableCall = false;
callback.apply(this, args);
setTimeout(() => enableCall = true, interval);
}
}
function helloFromThrottle(){
console.log("Jesus is saying hi!!!")
}
const foo = throttle(helloFromThrottle,5000)
foo()
As far as I understand, in simple terms
Throttling - similar to calling setInterval(callback) for certain number of times i.e calling same function for certain number of times over time on occurrence of event
and..
Debouncing - similar to calling setTImeout(callbackForApi) or calling a function after certain time has passed on occurrence of event.
This link can be helpful-
https://css-tricks.com/the-difference-between-throttling-and-debouncing/
For examples of typical uses cases, I recommend #Guy's answer. But the best way for me to understand these two concepts was to make it about pizzas. 🍕
Let's say you're an amazing pizza-maker, and so customers are in your shop constantly demanding more pizzas.
Throttling:
You decide you will only put out one pizza at the end of every hour, as long you received at least one request for pizza during that hour.
You receive 100 requests for pizzas in one hour, so you provide a pizza at the end of that hour. Then, you get no requests for pizza the next hour, so you don't put out a pizza. Then you get 10 requests for pizzas the next hour, and so you put out a pizza at the end of that hour.
Debouncing:
You are getting annoyed about your customers constantly demanding pizzas, and so you decide you will only give them a pizza after they have stopped asking you for a full minute.
They demand pizzas for 30 minutes straight, but then they stop asking for a minute after that. At that point, you will give them one pizza.
Then they demand pizzas for 5 minutes straight, and stop asking for a minute after that. At that point, you give them another pizza.
it’s in fact the way of limiting an event. For example, if you are listening on an event onclick, if it’s regular it will listen to every click you made.
If you use Throttle, it will set an interval between the time you want to listen to event for example listen to one click every second.
Debounce is a more restrictive one, it will only fire itself at the beginning or the ending of an event. For example, you are scrolling and you use Debounce, it will trigger only when you start and you finish to scroll.
Debounce:
Executes the function after the interval if function isn't being called within that interval.
Throttle:
Executes the function n times at fixed interval.
How debouncing works in hardware.
Debouncing is the process of removing noise from a digital signal. When a button is pressed, the signal bouncing around can cause the button to be registered as being pressed multiple times. Debouncing removes this noise so that the button is only registered as being pressed once. Picture a ruler being bounced on the edge of a desk, and imagine metal contacts inside a switch bouncing like this.
Better still, look at this diagram, showing the switch noise caused by bouncing.
We use resistors and capacitors of properly calculated ratings to smooth out the signal for n ms.
Explain how signal throttling works in hardware.
Signal throttling is the process of limiting the number of times a signal can be registered. This is often used to prevent a button from being registered as being pressed multiple times in a short period of time.
I prefer the term gating, but that's because I'm into electronic music production.
We open the gate at the end of each throttle period, and allow the signal to pass, and then close the gate again, for the next throttle period.
Explain how debouncing works in software.
Debouncing in software is often accomplished by using a timer. When the button is pressed, the timer is started. If the button is pressed again before the timer expires, the timer is reset. This ensures that the button can only be registered as being pressed once per debounce period.
In many implementations of debounce, we create a debounced version of the function which is embedded in a closure containing a timer (or gate). When the timer delay expires we set it it null again. The actual function only runs when the timer is null. Usually, this means when we first call the debounced function, it'll run once, then subsequent calls to it will be effectively cancelled until the delay time has elapsed.
In some implementations of debounce, while a stream of calls are fired and the timer hasn't expired, the timer will be restarted. Only calling the function after the bouncing has stopped. This is usually called a trailing debounce.
Explain how throttling works in software.
Throttling in software is often accomplished by using a counter. When the button is pressed, the counter is incremented. If the button is pressed again before the counter reaches a certain threshold, the counter is reset. This limits the number of times the button can be registered as being pressed in a given period of time. It's good to visualise this as a pulse or beat, which opens and closes a gate while calls are being sent to the throttle.
Rate limiting is another way to think of a throttle.
Why is this such a common cause of confusion?
In many many use cases a debounce or throttle will get you the results you want, especially if the software implementation you're using allows you to chain, trail, or lead your throttle / debounce.
Still, I hope all the answers here and this one have helped you understand more clearly.
They're very similar.
This article explains it rather well and has graphics too.
https://css-tricks.com/debouncing-throttling-explained-examples/
From the article (and with some clarifications):
The main difference between this (throttle) and debouncing is that throttle guarantees the execution of the function regularly, at least every X milliseconds.
Normally debounce calls the function at the end of a specified time and throttle calls when the first call to the throttled function is made. Sometimes debounce can take extra config that changes this to do the call at the beginning instead. Some implemenations of debounce can actually do what throttle does (see Lodash source code) when called with specific configs.
Simple concept for throttle is clicking the submit button frequently in a form, we need to use throttle. So the submit function is prevent from frequent clicks. It saves the same requests pass into the function.
And about debounce, write a simple code with input text tag for searching some data from the server. oninput, you use the debounce so it removes the previous requests and pass the last typed word to the server
const throttle = (callback, time = 0) => {
let throttle_req, count = 0;
return async function () {
var context = this, args = arguments;
if(throttle_req) return;
throttle_req = true;
if(time > 0)
{
callback.apply(context, args);
setTimeout(() => {
throttle_req = false;
}, time || 200)
}
else
{
let response = await callback.apply(context, args);
throttle_req = false;
return response;
}
}
}
const debounce = (callback, time = 0) => {
let debounce_req;
return function () {
var context = this, args = arguments;
clearTimeout(debounce_req)
debounce_req = setTimeout(() => {
debounce_req = null;
callback.apply(context, args);
}, time || 200)
}
}
How we call: Just wrap your function with throttle or debounce to check the difference
Throttle ex: same button click more than 1 time
var throttleFunct = throttle(function(num) {
console.log(num, "hello throttle")
}, 2000);
throttleFunct(300) //it execute. because its the first call
throttleFunct(400) //it won't execute
throttle async without time
var getDataAsync = throttle(function(id, name) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({name: name, id: id})
}, 2000)
})
});
async function test() {
let response = await getDataAsync(120, 'Sherley').then(resp => resp)
console.log(response, "respond") //it execute. because its the first call
response = await getDataAsync(120, 'James').then(resp => resp)
console.log(response, "respond2")//it executes 2 after first request
response = await getDataAsync(120, 'Jonathan').then(resp => resp)
console.log(response, "respond3")//it executes 3 after second request
}
test()
Debounce For ex: search box autocomplete
var debounceFunct = debounce(function(num) {
console.log(num+1)
}, 2000);
debounceFunct(300) //it won't execute and it cancelled
debounceFunct(400) // it executes and it replaced with the previous call. because this is the latest event fire
The major difference between debouncing and throttling is that debounce calls a function when a user hasn't carried out an event in a specific amount of time, while throttle calls a function at intervals of a specified amount of time while the user is carrying out an event.
What really matters here, in most simple terms: if you have some action, that is continuously repeated for some period (such as mouse movement, or page resize events), and you need to run some function in response, but you don't want to react to every action (cause it may detriment the performance), you have 2 options:
debounce - you skip all incoming actions, except the last one (the 'last one' is defined by the 'wait' time period you set for debounce function, for example, 2s - it will consider that actions flood stopped, if no actions were taken for 2s, and then it will react. This strategy is reasonable if you don't care about regular updates, you just need to react at least once.
throttle - if you want to react 'on schedule', to make regular updates even if actions flood is endless, you make your function run at regular intervals (no more often, then the specified time interval), for example 2s throttling will mean that your response will be executed an once if action is taken, but no less then 2s after that. So with continuous actions flood your response will be run on 0s, 2s, 4s, 6s, 8s...

Recursive function call with setTimeout limited to ~200 calls per second, why?

This code recursively calls the same function with a setTimeout of 1 millisecond, which in theory should call the function 1000 times per second. However, it's only called about 200 times per second:
This behavior happens on different machines and different browsers, I checked if it's has something to do with the maximum call stack, but this limit is actually way higher than 200 on any browser.
const info = document.querySelector("#info");
let start = performance.now();
let iterations = 0;
function run() {
if (performance.now() - start > 1000) {
info.innerText = `${iterations} function calls per second`;
start = performance.now();
iterations = 0;
}
iterations++;
setTimeout(run, 1);
}
run();
<div id="info"></div>
There’s a limitation of how often nested timers can run. The HTML5 standard says: 11: "If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4."
This is true only for client-side engines (browsers). In Node.JS this limitation does not exist
HTML Standard Timers Section
Very similar example from javascript.info
The delay argument passed to setTimeout and setInterval is not a guaranteed amount of time. It's the minimum amount of time you could expect to wait before the callback function is executed. It doesn't matter how much of a delay you've asked for, if the JavaScript call stack is busy, then anything in the event queue will have to wait.
Also, there is an absolute minimum amount of time you could reasonably expect a callback to be called after which is dependent on the internals of the client.
From the HTML5 Spec:
This API does not guarantee that timers will run exactly on schedule.
Delays due to CPU load, other tasks, etc, are to be expected.
I once read somewhere that it was around 16ms so setting a delay of anything less than that shouldn't really change the timings at all.

Javascript setTimeout timing reliability

I have recently started exploring Javascript in more detail, and how it executes within the browser. Specifically, the setTimeout function.
My understanding is that calling setTimeout(foo,x)
will pass a handle to foo to be executed after x milliseconds. How reliable is this timing? Obviously if another long-running script is still executing after x milliseconds then the browser won't be able to call foo, but can I be absolutely certain that setTimeout(foo,101) will always be executed after setTimeout(foo,100)?
First of all, the timeout is in miliseconds, therefor 1 sec = 1000 ms. consider that.
you can always be sure that delay of 1001 will be later than 1000.
BUT You must remember that if the 2nd methods relay on changes of the first method it doesnt mean it will work good.
the first methods can take for reasonable time of 3ms (not a complicated one) and the 2nd one can start only 1 ms after the first one causing your reliability on the first method to fail.
i would suggest not to use this feature but in some rare cases.
you can tag me in this answer comment for your specific case and i can suggest the right way to work it out.
In nodejs we may be able to time events very precisely by setting a timeout to expire shortly before the desired moment, and then creating a tight series of event-loop ticks, and after each one checking how close to the target time we've approached:
Imagine Date.now() is currently, e.g., 11000 (unrealistic; just an example!)
Determine we want to act in EXACTLY 4000ms
Note that means EXACTLY when Date.now() === 15000
Use setTimeout to wait less than 4000ms, e.g., 3800ms
Keep awaiting microticks until Date.now() >= 15000
This won't block the event loop
(But it will keep your CPU very busy)
let preciseWaitMs = async (ms, { nowFn=Date.now, stopShortMs=200, epsilonMs=0 }={}) => {
let target = nowFn() + ms;
await new Promise(resolve => setTimeout(resolve, ms - stopShortMs));
// Allow `epsilonMs` to shift our wait time by a small amount
target += epsilonMs;
// Await a huge series of microticks
// Note: this will eat cpu! Don't set `stopShortMs` too high!
while (target > nowFn()) await Promise.resolve();
};
(async () => {
let t1 = Date.now();
let target = t1 + 2000;
console.log(`Trying to act in EXACTLY 2000ms; at that point the time should be ${target}`);
await preciseWaitMs(2000);
let t2 = Date.now();
console.log(`Done waiting; time is ${t2}; deviation from target: ${t2 - target}ms (negative means early)`);
})();
Note that preciseWaitMs(4000) will never wait less than 4000ms. This means that, if anything, it is biased towards waiting too long. I added an epsilonMs option to allow the bias to be moved back according to the user; for example preciseWaitMs(4000, { epsilonMs: -1 }) may cancel out preciseWaitMs's bias towards always being late.
Note that some js environments provide a higher-precision current-time query than Date.now - for example, nodejs has require('perf_hooks').performance.now. You can supply a function like this using the nowFn option:
{ epsilonMs: -0.01, nowFn: require('perf_hooks').performance.now };
Many browsers support window.performance.now; try supplying:
{ epsilonMs: -0.01, nowFn: window.performance.now };
These settings achieve sub-millisecond "precise" timing; off by only about 0.01ms on average
Note the -0.01 value for epsilonMs is what seemed to work best for my conditions. Note that supplying fractional epsilonMs values is only meaningful if nowFn provides hi-res timestamps (which isn't, for example, the case with Date.now).
Most browsers use single thread for UI and JavaScript, which is blocked by synchronous calls. So, JavaScript execution blocks the rendering.
Events are processed asynchronously with the exception of DOM events.
but setTimeout(function(),1000) trick is very useful. It allows to:
Let the browser render current changes. Evade the “script is running too long” warning.
Change the execution flow. Opera is special in many places when it comes to timeouts and threading.
So if another function is executing it will handle it by running in parallel.
another thing to setTimeout(function(),1000) her time is in millisecond not in seconds.

Is it possible to create 2 loops in javascript where one loop will be prioritized in case of resource deficiency?(both handle game ticks)

The problem is as such:
In a js and asm.js based multiplayer game I've got two loops.
One handles the actual game ticks, like unit position, velocity and combat.
The other handles rendering of this world onto the canvas for the user to see.
What I'd like to happen is when the processor/GPU(they made those the same thing on some machines now, can't say I'm happy about that) gets encumbered too much the rendering loop should skip and thus stop changing the canvas. I.e. freezing the game screen in a lag pike.
Meanwhile the little processing power left is used to successfully complete the actual game tick preventing de-synchronisation with other game clients.
(It's an RTS-like game when it comes to load so the user input instead of positions of all objects are sent over the net).
Failing this the client would have to be kicked by the other clients or all clients would have to pause for him to reconnect and resync. i.e. bad bad bad!
A sloppy makeshift way to do this would probably be by using timestamps and terminate the graphic loop if it won't be complete by a certain time. One would presumably do this by determining max execution time for the packet types on the stack of the loop and immediately terminate the loop if the "time to execute value" of all packets together is too great to be dealt with within the resource capacity the timestamps are indicating by slowdown measurement. Hell, maybe that's radical but perhaps even skip-terminating the graphic loop when any slowdown is detected just to be sure to avoid desync.
So priorotizing one loop over another(both handling ticks) and making the second one skip if a shortage in resource is detected to ensure the first one always completes it's tick within each timeframe(10 ticks per second here).
Any possibilities or best practice methods you guys can inform me on?
EDIT: Please focus on the ability to measure availability of cpu resources and the skipping/termination for one tick of the graphic loop if these resources would not available enough to finish both loops (i.e. if the loops won't finish in the 100ms timeframe after which the next loop tick should already be firing, don't start/terminate the graphics loop).
One solution would be to use a web worker to do your world update loop and then the normal javascript loop to do the render. You would need to hand the state back and forthright o /from the web worker but the render loop would only draw on the updated data.
An advantage is that you could still have reactionary display code on the main ui loop.
This also have the advantage of the fact that the web worker could be using a different core and with multiple web workers you could use multiple extra cores
Fo the logical loop, i would take setInterval, and for the paint - requestAnimationFrame. And even more - the callback at requestAnimationFrame also receives a timestamp, so you can track timestamps and skip single frame if some lack appear.
the processor is able to handle other tasks while also rendering the animation
This statement is wrong - processor can handle only one task, and requestAnimationFrame is not actually the Rendering, it is your callback - generic javascript. You can think about it like a setTimeout. The only difference is, that it tries to run the callback on next free framerate's frame. That's why it is much better than setTimeout. So for the animations you must use the requestAnimationFrame. Other good part about it is, when the webpage is in background(other tab opened). Then the callback wont be called until it comes to the foreground. This saves processor time, as nothing is calculated in that callback.
Going back to your question: You now but, that only one callback can be processed in a time, so if the processor is in a particular time busy with the logical function, then the callback of the animation loop won't be fired. In that case it calls 'lag'. But as I understood, it is actually the desired behavior - to give the logical callback function more time. But there is other side. What if your animation function is busy, when the time for logical function came to be fired? In this case it will be fired only when animation function ends. There is nothing to do about it. If your animation function is 'heavy', you could only try to split it for 2 frames. One frame - prepare everything for render, the second one - render.
But anyway, you never become millisecond-perfect interval or timeout in javascript. As it want be called until event-loop is not free. To get the idea:
var seconds = 0;
setInterval(function(){ seconds++; var x = 10e8; while(--x); }, 1000);
Depends on you CPU, but after 10 seconds time, variable 'seconds' will be much less then 10.
And one more thing, if you really rely on time, then it is safer to use Date.now() to synchronize next logical tick:
var setLogicalLoop = (function(){
var _startedAt,
_stop,
_ms;
function frame(){
if (_stop === true)
return;
// calculations
var dt = Date.now() - _startedAt,
diff = dt % _ms;
setTimeout(frame, ms - diff);
};
return function (callback, ms){
_startedAt = Date.now();
_stop = false;
setTimeout(frame, ms);
return function(){
_stop = true;
};
};
});
// -> start
var stopLoop = setLogicalLoop(myFunction, ms);
// -> stop
stopLoop();

prevent javascript setInterval function stacking up

I have a function that runs on a click event that uses javascript's setIterval for some of my animations (i'm doing a game) so the problem is that if a user clicks while the animation is still displaying (setInterval is still executing) the setInterval is stacking up in the event stack or that is what I found out thus either crushing my game or running twice as fast (the animation). My question is is there any way to prevent event stacking? I do not want the setInterval to stack up on the previous setInterval and so on. I know that I could use clearInterval function like so:
var timerInterval = setInterval(drawPlayerRunning, 50);
clearInterval(timerInterval);
but it does not really work as I want it to, because what if user clicks many times while the function is still is executing, the clearInterval will only get rid of last event of the event stack leaving all the previous ones still in the "game". Any idea how to prevent this event stack up, or at least removing them efficiently?
You can create a flag that monitors the interval state:
1)
var isIntervalInProgress = false;
setInterval(function()
{
if ( isIntervalInProgress )
return false;
isIntervalInProgress = true;
drawPlayerRunning();
isIntervalInProgress = false;
}, 50);
or just a timeout that will run itself once it's finished:
2)
var func = function()
{
setTimeout(function()
{
drawPlayerRunning();
func();
}, 50)
}
whichever you like
You want to use requestAnimationFrame. It is designed with games in mind, and if your code happens to be too slow, it will reduce your frame rate accordingly (from 60 fps to 30 fps for instance). But it won't stack-up events.
Edit: Sorry, I think I misunderstood your question. Let me try again.
You should have only one draw function which is called every few milliseconds (set the interval up with requestAnimationFrame(draw)).
A click should not add a new interval, but rather create a floatingAnimation object and add it to the list of objects to render. All animation objects will be rendered by the draw function everytime the browser calls draw. In the arguments passed to draw, there will be a timestamp. Use this timestamp minus the creation date of floatingAnimation to determine how to draw the floating thing above the character.

Categories