Atlas 6: When ‘this’ is not really ‘this’

Atlas callbacks are not executed on the same context where they
are called. For ex, if you are making a Page method call from a
javascript class like this:

function SampleClass() { this .id =
1 ; this
.call = function () {
PageMethods.DoSomething(
Hi
, function (result) { debug.dump( this .id ); }
); } }

What happens when you call the “call” method? Do you get “1” on
the debug console? No, you get “null” on the debug console because
“this” is no longer the instance of the class. This is a common
mistake everyone makes. As this is not yet documented in Atlas
documentations, I have seen many developers spend time finding out
what’s wrong.

Here’s the reason. We know whenever Javascript events are raised
“this” refers to the html element which produced the event. So, if
you do this:

function SampleClass() { this .id =
1 ; this
.call = function () {
PageMethods.DoSomething(
Hi
, function (result) { debug.dump( this .id ); }
); } }

If you click the button, you see “ButtonID” instead of “1”. The
reason is that, the button is making the call. So, the call is made
within button object’s context and thus “this” maps to the button
object.

Similarly, when Xml Http raises the event onreadystatechanged
which Atlas traps and fires the callback, the code execution is
still on the Xml Http’s context. It’s Xml Http object which raises
the event. As a result, “this” refer to the Xml Http object, not to
your own class where the callback is declared.

In order to make the callback fire on the context of the
instance of the class so that “this” refers to the instance of the
class, you need to make the following change:

function SampleClass() { this .id =
1 ; this
.call = function () {
PageMethods.DoSomething(
Hi
, Function.createDelegate( this ,
function (result) { debug.dump( this .id ); }
) ); } }

Here, the Function.createDelegate is used to create a delegate
which calls the given function under the “this” context.
Function.createDelegate is defined in AtlasRuntime:

Function.createDelegate
= function (instance, method) { return function ()
{
return method.apply(instance, arguments); }
}

3 thoughts on “Atlas 6: When ‘this’ is not really ‘this’”

  1. Hi Omar.
    I am having the problem you described above where Atlas is returning after a webservice call into a different context, and so “this” no longer refers to the javascript class that made the original call. Unfortunately your solution of using the following client-side code:

    function SampleClass() {
    this.id = 1;
    this.call = function() { PageMethods.DoSomething( “Hi”, Function.createDelegate( this, function(result) { debug.dump( this.id ); } ) ); } }

    isnt working for me. when I execute the call method, I get back null rather than “1” (the id specified in the class).

    Any ideas how I might get the callback to be in the context of my class so that I can refer to other members of the class?

    Thanks

  2. Hi

    I have a weird problem with Pagemethods as well:

    1. I use “PageMethods” to call the function on the ASPX Page. This method is a static method and it is **NOT IN** my code behind file. It is decorated by “webmethod” and “scriptmethod” attributes as required by Ajax Extensions Beta 1. I use javascript to invoke the “PageMethods.” on click of a button.

    2. The called method returns a message from resource file at the folder App_GlobalResources. I have 2 variations of the resource file (ta-IN and the base en-US)

    3. The page culture is set to “auto” and uiculture also “auto”

    4. In my internet explorer , languages section I have kept “ta-IN” as first preference and “en-US” as second.

    5. When the page is loaded all the controls are localized correctly to “ta-IN”. But atlas callbacks using “PageMethods.” do not recognize the culture and always return the string from “en-US” files.

    6. I debugged a call back to find System.Threading.Thread.CurrentCulture and System.Threading.Thread.CurrentUICulture as “en-US” during callbacks whereas other page processing events such as PageLoad , prerender it is correctly set to “ta-IN”.

    So the question is how do I get my callbacks to return correct strings in sync with the page localization. Thanks for your time and effort.

  3. Shame I missed this one at the time.. 🙂

    This problem always was a classic in javascript i.e. closures get executed in global scope – but the workaround is this:

    function SampleClass()

    {

    this.id = 1;

    this.call = function()

    {

    var obj = this;

    PageMethods.DoSomething( “Hi”, function(result)

    {

    debug.dump( obj.id );

    } );

    }

    }

    I feel like it’s 1999 again 😉

Leave a Reply