Dave Crane
2007-Apr-12 09:36 UTC
Re: Using Ajax.Request, How can I access to parent context inside onSuccess callback ?
Hi, Use a closure - if you reference the variable a inside the anonymous function assigned to the onSuccess callback, the interpreter will preserve a reference to it. So: function test() { var a = ''test''; new Ajax.Request(''/myurl'', { method:''get'', onSuccess: function(transport) { alert("a = "+a); } } ); } should work... Note that I just mention ''a'' inside the onSuccess fn, no special syntax is needed. The same technique works for UI callbacks too - great once you start programmatically assigning UI event handlers inside objects, rather than the old onclick attributes and pals. Closures are a very powerful feature of JavaScript, enabling a much more fluid style of coding than the pure OO approach. Once you start getting your head around them, they can''t be beat. HTH Dave On Thursday 12 April 2007 11:15, scramatte wrote:> When I made an Ajax Request, how can I access to parent context > inside onSuccess callback. > I mean that in the example below I would like to get value of var > "a"---------------------- Author Ajax in Action http://manning.com/crane Ajax in Practice http://manning.com/crane2 Prototype & Scriptaculous in Action http://manning.com/crane3 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Yanick
2007-Apr-12 14:02 UTC
Re: Using Ajax.Request, How can I access to parent context inside onSuccess callback ?
Like Dave said, closures may be hard to understand at first, but it is, in fact, one of the most important thing to understand when writing JS scripts. Consider this : ---------------------------------------------------- var AjaxEngine = Class.create(); ajaxEngine.prototype = { initialize: function(id) { this.id = id; }, request: function(url, callback) { var options = { method: ''get'', onSuccess: function() { callback(this.id); } }; new Ajax.Request( url, options ); } }; var successFn = function(id) { alert( id ); }; new AjaxEngine("test").request( "page.php", successFn ); ---------------------------------------------------- (Let suppose the file page.php exists on the server, and the onSuccess method of the ajax request is executed) What do you think will be the output printed in the alert box ? If you say "test", guess again. Why ? Who called the onSuccess function ? The object AjaxEngine never calls anything except the method Request of the new Ajax object (new Ajax.Request...). In fact, it is that Ajax object who called it, so the keyword ''this'' refers to that object. For this reason, ''this.id'' is ''undefined''. Therefore, in this particular script, it is impossible to know what AjaxEngine object was successful. To return the information we need, we must "bind" the function so it will always be called in a particular context. Fortunatly, Prototype offers that function : bind(), which is a member of the Function prototype. Consider replacing the line : onSuccess: function() { callback(this.id); } by onSuccess: function() { callback(this.id); }.bind(this) Since the onSuccess assignement is executed in context of the AjaxEngine (we called new AjaxEngine().request....) then the binding is done with the AjaxEngine object (this). For this reason, the ''this'' inside the function, however the function may be called, is always the same this as the one ''this'' used to bind the function with. With this modification, the alert will display "test". The keyword ''this'' always refers to the exact object used to call the function. As this : var Example = function(id) { this.id = id; }; Example.prototype = { func: function() { alert(this.id); } } var obj1 = new Example("test1"); var obj2 = new Example("test2"); obj1.func(); // will output "test1" obj2.func(); // will output "test2" obj1.func.bind(obj2).call(); // will output "test2" because of binding I suggest you familialize yourself with closures and binding, so you will minimize the chance your code will be messy, hard to maintain, and cause memory leaks. -yanick On 12 avr, 05:36, Dave Crane <d...-qrf20pp95eSLQvtTh0HkdajZmZ73YKuj@public.gmane.org> wrote:> Hi, > > Use a closure - if you reference the variable a inside the anonymous function > assigned to the onSuccess callback, the interpreter will preserve a reference > to it.[snip] --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---