views:

4060

answers:

7

Hi,

I have an application that uses Ajax.Request and its onSuccess event handler in lots of places.

I need to call a function (that will check the response) before all these onSuccess events fired. I tried using Ajax.Responders.register with onComplete event but it fires after Ajax.Request's onSuccess event. Any suggestions?

Thanks,

+1  A: 

You can run your method before the other code in onSuccess and return false if something is wrong.

vimpyboy
Yes you are right but i have lots of onSuccess event already registered everywhere. What I am trying to do is just extending base onSuccess event.
matte
I understand your problem. But what if you create a new function where that uses the Ajax.Request, but first adds your check? It´s not a sexy solution, but it might work.
vimpyboy
That is also right but if i do that way, i need to replace every Ajax.Request call with that new function. It may sound "lazy" to you but there is looots of calls to Ajax.Request :)
matte
+3  A: 

There are several events to chose from. Here is the event chain for Ajax.Request:

  1. onCreate
  2. onUninitialized
  3. onLoading
  4. onLoaded
  5. onInteractive
  6. onXYZ, onSuccess or onFailure
  7. onComplete

onLoading, onLoaded, onInteractive sound interesting, but according to the spec they are not guaranteed to happen. That leaves you with the possibility to hook on to onCreate, which is called just after the request object is build, but before the request is actually made.

Tomalak
Hi Tomalak, as you have said onCreate is called before the request is made. But what i need is to process the response so it is not an option for me.
matte
Then you want onSuccess. There is no way around it. All you can do is put in your sanitizing/checking function at the start of each onSuccess call. (Or you patch it into the Prototype JavaScript library, but down this road lies madness.)
Tomalak
A: 

"General solution" - independent upon JS framework (kind of)

var oldFunc = Ajax.Request.onSuccess; Ajax.Request.onSuccess = function foo() { alert('t'); oldFunc.apply(this, arguments); }

This will "extend" your JS function making it do exactly what it used to do except show an alert box every time before it executes...

Thomas Hansen
+1  A: 

This might be a little late, but for the benefit of anyone else wondering about the same problem I will propose this solution:

You can use Prototypes own implementation of aspect-oriented programming to do this. Granted you will have to modify all your onSuccess-parameters, but it can be done with a simple search-and-replace, instead of updating all your callback functions. Here is an example Ajax.Request creation:

new Ajax.Request('example.html', {
    parameters: {action: 'update'},
    onSuccess: this.updateSuccessful
});

Say you have similar code snippets spread all over your code, and you want to preceed them all with a certain function that validates the response before the actual function is run(or even prevented from running at all). By using Funtion.wrap supplied in Prototype we can do this by extending the code above:

new Ajax.Request('example.html', {
    parameters: {action: 'update'},
    onSuccess: this.updateSuccessful.wrap(validateResponse)
});

Where 'validateResponse' is a function similar to this:

// If you use the X-JSON-header of the response for JSON, add the third param
function validateResponse(originalFn, transport /*, json */) {
    // Validate the transport

    if (someConditionMet) {
        originalFn(transport /*, json */);
    }
}

Thus you have extended your onSuccess-functions in one central place with just a quick search for onSuccess and pasting in 'wrap(validateResponse)'. This also gives you the option of having several wrapper-functions depending on the needs of the particular Ajax-request.

Aleksander Krzywinski
+1  A: 

similar to Aleksander Krzywinski's answer, but I believe this would prevent you from having to sprinkle the use of "wrap" everywhere, by consolidating it to the onCreate Responder.

Ajax.Responders.register({

  onCreate: function(request) {

    request.options['onSuccess'] = request.options['onSuccess'].wrap(validateResponse);

  }

});
seth
A: 

Don't know if this is the cleanest solution, but for me it did the trick.


var tmp = Ajax.Request;
Ajax.Request = function(url, args) {
 // stuff to do before the request is sent
 var c = Object.clone(args);
 c.onSuccess = function(transport){
  // stuff to do when request is successful, before the callback
  args.onSuccess(transport);
 }

 var a = new tmp(url, c);
 return a;
}
Ajax.Request.protoype = new tmp();
Ajax.Request.Events = tmp.Events;
delete tmp;
Gabi Purcaru
A: 

I'm not sure if the language has been a barrier, I've had that problem myself before, but you mixed terms quite a few times (mix between events, handlers, elements) that did not help.

Thanks, Abe - silver coins

Abigail