JavaScript: Don’t spam your server, Debounce and Throttle

If you make server call-backs or update the browser GUI based on user interaction you can end up doing far more updates than necessary…

In fact on one occasion, during Illyriad-beta testing, we started tripping our server’s dynamic IP request rate throttling and banning our own IP address – D’oh!

Common situations where over responding to events are mousemove, keypress, resize and scroll; but there are a whole host of situations where this applies.

We update our pages dynamically via ajax, based on user clicks around the user interface. In this situation if the user makes several page navigation requests in quick succession – the only important one to be made is the last, as for all the previous ones the data will be thrown away. So why make the requests in the first place? It’s just unnecessary server load.

Equally, if a user is moving an mouse around a map and you are updating UI coordinates for every pixel change the mouse makes, it potentially a huge number of DOM updates far beyond the perception of a user; for no real benefit, but it will cause a degradation in performance.

Initially, we controlled the situation using complex setups of setTimeout clearTimeout and setInterval. However, as the various places we made use of this became more varied, with different sets of needs, the code became more and more complex and difficult to maintain.

Luckily, it was around this time we discovered Ben Alman’s jQuery plugins debounce and throttle; which are extremely powerful – yet simple to use of and cover a whole host of permutations.


Using his  jQuery $.throttle, you can pass a delay and function to $.throttle to get a new function, that when called repetitively, executes the original function no more than once every delay milliseconds.

Throttling can be especially useful for rate limiting execution of handlers on events like resize and scroll. Check out the example for jQuery throttling.


Using his jQuery $.debounce, you can pass a delay and function to $.debounce to get a new function, that when called repetitively, executes the original function just once per “bunch” of calls, effectively coalescing multiple sequential calls into a single execution at either the beginning or end.

Debouncing can be especially useful for rate limiting execution of handlers on events that will trigger AJAX requests. Check out the example for jQuery debouncing.

In fact its well worth checking out all Ben Alman’s jQuery Projects as they are full of little wonders, that you soon are sure how you did without them!

(Fix) Memory Leaks: Ajax page replacement

Resolving memory issues with HTML replacement and Ajax

In Illyriad we do very large numbers of ajax requests using jQuery over a players session. Some of these are pure data requests, but many of them are navigational HTML page replacements.

A simple replacement seems to leak memory in various browsers:

[code lang=”js”]

Even calling the jQuery function .empty() before the replacement doesn’t seem to help in all cases. To fix this we have created a clean up function which is a common or garden “overkill” variety which seems to do the trick. Usage below:

[code lang=”js”]
function ChangeLocationSucess(data, textStatus, XHR) {
if (XHR.status == 200) {
var div = $(‘#ElementToReplaceContents’);
DoUnload(); // More on this further down
div.RemoveChildrenFromDom(); // Clean up call
div.html(data); // HTML replacement


Clearing the memory from the existing HTML is done with the clean up code below:

[code lang=”js” title=”Added: RemoveChildrenFromDom jQuery plugin”]
(function( $ ){
$.fn.RemoveChildrenFromDom = function (i) {
if (!this) return;
this.find(‘input[type="submit"]’).unbind(); // Unwire submit buttons
.empty() // jQuery empty of children
.each(function (index, domEle) {
try { domEle.innerHTML = ""; } catch (e) {} // HTML child element clear
this.empty(); // jQuery Empty
try { this.get().innerHTML = ""; } catch (e) {} // HTML element clear
})( jQuery );

Some pages have extra resources cached and extra elements with wired up events. For these we have introduced a DoUnload function which also gets called before the replacement. This runs through the list of on page clean up functions and calls them one by one:

[code lang=”js” title=”Extra clean up system”]
var unloadFuncs = [];
function DoUnload() {
while (unloadFuncs.length > 0) {
var f = unloadFuncs.pop();
f = null;

We create these unload functions on the page that has any extra clean up to do by using the following code; which adds clean up functions to the unloadFuncs array above. This code looks like the code below:

[code lang=”js” title=”On page clean up registration”]
var unload = function() {
OnPageCachedResources.clear(); // Clear array of cached resources
OnPageCachedResources = null;
.undelegate(); // Remove attached events

Obviously this varies from page to page and most of our pages don’t need it – at which point the DoUnload function just returns with out doing work.

This coupled with the Fix for IE and JQuery 1.4 Ajax deal with most of the regular unexpected leaks.

(As an aside: When replacing HTML with Ajax, do not wire up events using onclick=”” etc in the HTML or this will also leak. Use event binding from script – a third party library like jQuery, Prototype or Dojo will make this very straight forward)

(Fix) Memory Leaks: IE and JQuery 1.4 Ajax

While testing Illyriad we found that over time the browsers IE7 and IE8 leak memory on Ajax calls using JQuery 1.4.

If you make a lot of ajax calls without changing page this can build up quite quickly and start causing issues. This is caused by the onreadystatechange event not being detached and IE not garbage-collecting the associated memory.

To fix this, locate these lines in the source JQuery file; already kindly annotated with “Stop memory leaks”:

[code lang=”js” firstline=”6019″ title=”Original jquery-1.4.4.js”]
// Stop memory leaks
if ( s.async ) {
xhr = null;

Add in these extra lines to change them to the following (we detach the abort event also for good measure):

[code lang=”js” firstline=”6019″ title=”Modified jquery-1.4.4.js”]
// Stop memory leaks
if ( s.async ) {
try {
xhr.onreadystatechange = null;
xhr.abort = null;
} catch (ex) { };
xhr = null;

Don’t forget to minify your jquery file before including it. [We prefer using UglifyJS]

Also rename it slightly so users with cached versions pick up the new file

e.g. jquery-1.4.4a-min.js