jQuery – Remove handlers from global AJAX functions

If you’ve used the jQuery Ajax functionality, you may be familiar with the Global Ajax Event Handlers, a nice set of functions for binding callbacks on to the various stages of an Ajax request. For instance, you can bind functions on ajaxSend and ajaxComplete, which are called when the request is sent and completely successfully, respectively, to show a “Saving…” and then “Saved” message. You could also bind a handler onto ajaxError, which is called whenever the request fails, to pop up a dialog describing what happened. This way, you don’t have to copy and paste a bunch of handling code throughout your various $.ajax calls, and instead can handle them in one centralized location.

Unfortunately, while the jQuery team provides great methods to assign handlers to these events, they don’t have any (at least, that I’ve seen), to remove those handlers from their respective events, as you can with jQuery’s .on() and .off(). While they may not have been a huge issue a few years ago, as the global handlers are reset every time the page reloads, it’s become more of a problem with the emergence of single-page applications, where the page may not necessarily refresh before loading a new page.

We ran into this problem in a site I manage that uses this architecture, where navigating to a new page would tack on an additional ajaxSend and ajaxComplete handler, without removing the old one. Since there is no clear method to remove these handlers, and I couldn’t find any solution looking around online, I started to dig into the jQuery source, hoping to find the underlying way these were stored to see if I could find a way to remove them manually. What I found was actually pretty interesting:

// Attach a bunch of functions for handling common AJAX events
jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
	jQuery.fn[ type ] = function( fn ){
		return this.on( type, fn );
	};
});

For setting up each global event, they simply run a loop for each event name, and create a new function with that name that aliases to .on() with the function/event name as the event type. This is essentially saying at each function translates to the following:

$.fn.ajaxStart = function ( handler ) { return this.on('ajaxStart', handler); };
$.fn.ajaxStop = function ( handler ) { return this.on('ajaxStop', handler); };
$.fn.ajaxComplete = function ( handler ) { return this.on('ajaxComplete', handler); };
$.fn.ajaxError = function ( handler ) { return this.on('ajaxError', handler); };
$.fn.ajaxSuccess = function ( handler ) { return this.on('ajaxSuccess', handler); };
$.fn.ajaxSend = function ( handler ) { return this.on('ajaxSend', handler); };

Sure enough, further down in the code, I found some evidence to confirm this. Within the bowels of the $.ajax() function lies this code:

if ( fireGlobals ) {
	globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
	// Handle the global AJAX counter
	if ( !( --jQuery.active ) ) {
		jQuery.event.trigger("ajaxStop");
	}
}

The line is question is globalEventContent.trigger("ajaxComplete", [jqXHR, s]); which uses .trigger() to force a ajaxComplete event to be fired, which will be handled by the previous .on() statement. To test my theory, I tried the following in the clean-up routine of the page, which is called whenever the user navigates to a new page:

// .ajaxComplete() and .ajaxSend() should always be attached to the document,
// so we will try to unbind them from there as well
$(document).off('ajaxComplete').off('ajaxSend');

And sure enough, it worked perfectly. The handlers were unbound on each page navigation and re-bound when the page was re-loaded. Instead of having each handler stack up until it was called hundreds of times on each ajax request.

Remember, you can also target specific functions like you would with .off().

Also read...

Comments

  1. Pingback: MapihBVe

  2. Heya i came for the first time here. I came across this board and I find It truly useful & it helped me out much. I hope to give something back and aid others like you helped me.

    Reply
  3. I not to mention my pals happened to be reading through the nice tricks from the blog then at once developed a horrible suspicion I had not expressed respect to the web blog owner for those tips. All of the young men happened to be as a result happy to learn all of them and now have without a doubt been using those things. Appreciate your turning out to be so helpful and for having such decent guides millions of individuals are really needing to discover. Our sincere apologies for not saying thanks to you sooner.

    Reply
  4. Only wanna input on few general things, The website style is perfect, the subject matter is real great : D.

    Reply
  5. This is very interesting, You’re a very skilled blogger. I have joined your rss feed and look forward to seeking more of your great post. Also, I have shared your web site in my social networks!

    Reply
  6. Simply wanna input on few general things, The website pattern is perfect, the written content is really great : D.

    Reply
  7. This is very interesting, You are a very skilled blogger. I have joined your rss feed and look forward to seeking more of your excellent post. Also, I have shared your web site in my social networks!

    Reply
  8. Hello.This post was extremely interesting, particularly because I was investigating for thoughts on this topic last couple of days.

    Reply
  9. Excellent which i always been trying to find. Pleased with some of our writer in terms of your ingestion with their timeframe this time around.

    Reply
  10. Actually This post is exactly what I am interested. we need some more good information. Please add more good information that would help others in such good way.This post is exactly what I am interested. we need some more good information. Please add more good information that would help others in such good way.i Will used it again.

    Reply
  11. Magnificent i always remained wanting to seek out. Thanks if you want to the writer when considering thinking of the useful moment these times.

    Reply
  12. I can’t understand how to add your weblog to my news reader. any recomendations would be appreciated I want to access your posts.

    Reply
  13. Pingback: Anonymous

  14. Pingback: Anonymous

  15. Everything is very open with a very clear explanation of the challenges. It was definitely informative. Your website is very helpful. Many thanks for sharing!

    Reply
  16. very few internet websites that come about to become detailed below, from our point of view are undoubtedly well worth checking out

    Reply
  17. I just like the helpful information you supply in your articles. I’ll bookmark your weblog and take a look at once more here regularly. I’m relatively certain I’ll be told a lot of new stuff right right here! Best of luck for the next!

    Reply
  18. I simply want to say I am new to blogging and truly enjoyed your blog. Most likely I’m want to bookmark your site . You definitely come with impressive article content. Thanks for sharing with us your webpage.

    Reply
  19. I simply want to mention I am beginner to blogging and site-building and truly enjoyed your blog. More than likely I’m going to bookmark your site . You certainly have amazing writings. Thanks a lot for sharing your webpage.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>