4

I have an application using Backbone.js that has various AJAX requests. I want to be able to intercept all AJAX requests and do some pre and post request functions without having to specify these functions at the point of definition.

An example of what I want to do is if the response from the request indicated that the user is not logged in, then a full screen modal is displayed.

I have looked at doing something like the following via jQuery:

jQuery.ajaxSetup({
  beforeSend: function() {
     return console.log("mybefore");
  }
});

but this seems to miss XHR requests using sockets.

I have also briefly looked at doing something like the following:

XMLHttpRequest.prototype.reallySend = XMLHttpRequest.prototype.send;
XMLHttpRequest.prototype.send = function(body) {
    console.log('mybefore');
    this.reallySend(body);
};

With this example, I wasn't sure how to do the after

So after all that, my question is: Is there an elegant way of overriding ajax functions to do pre and post processing without altering the way requests can be made.

(Any backbone.js specific solutions would be nice too)

neolaser
  • 6,722
  • 18
  • 57
  • 90
  • 2
    For backbone specifically, you would override `Backbone.sync`. For jQuery, you have already figured it out. To go around both and handle `XMLHttpRequest` directly... What do you want this hijacking to do? Just to log? Or to modify stuff? – Shadow Man May 29 '13 at 00:41
  • More than just log. Not necessarily make changes to the original request (although this could be an option) it is more performing actions before and after the request. – neolaser May 29 '13 at 00:56
  • Why can't you use `jQuery` or `Backbone` to create your request rather than creating `XMLHttpRequest` directly? Anything you could do to modify that behavior directly (through overriding prototypes) is likely to appear an ugly hack to anybody who sees the code (personally I think the above `reallySend` method is a hack). Perhaps you could wrap `XMLHttpRequest` in some locally defined `CustomXMLHttpRequest` if you really can't use `jQuery`? – Shadow Man May 29 '13 at 01:08
  • Yeah I do think the reallySend is a hack aswell! I was trying to achieve an agnostic method of completing this. The application I am working with has been built with a mixture of jQuery and Backbone implementations of XHR calls. So my thought was that they both end up at XMLHttpRequest.prototype.send...right? (maybe thats not the case :) ) – neolaser May 29 '13 at 01:17
  • That is an implementation detail. Maybe they do all call `send` but even so can you guarantee that they do not (and never will) override the send method? Since you have no control over the libraries, you can only say what the current version you are using does. Whenever possible you should be using the APIs as they were intended. They are likely to stay the same even when the implementation changes to use a new method to speed things up or fix some bugs. – Shadow Man May 29 '13 at 01:34
  • This worked, except ie8 duplicates the "send" function when you put it back in. This is a dump of XMLHttpRequest.prototype from ie8 after running your code: abort : abort(), getAllResponseHeaders : getAllResponseHeaders(), getResponseHeader : getResponseHeader(), open : open(), reallySend : send(), send : function(), send : function(), setRequestHeader : setRequestHeader() – tripRev Jul 19 '13 at 16:19

1 Answers1

0

You need to do something like this.

CoffeeScript Code

define [
    'jquery'
], ($) ->
   loadElement = $('someContent')

   $(document)
      .ajaxStart(-> $(loadElement).show())
      .ajaxStop(-> $(loadElement).hide())
rcarvalho
  • 790
  • 1
  • 4
  • 14