How to get teh controller "this." in a event callback

86 views
Skip to first unread message

PatrickR

unread,
Sep 30, 2010, 12:00:06 PM9/30/10
to JavaScriptMVC
Hi,

I have a controller Foo and in it an OpenAjax event callback
myevent.bar(topic, data) and another function bim(). How do I within
the callback get the controller scope from within the callback bar to
call bim()?

$.Controller.extend('Foo',{},
{
'myevent.bar.** subscribe': function(topic, data) {
var me = $("#foo").controllers()[0]; // what i do now. Is
there a better way?
me.bim();

this.bim(); // won't work. this is the OpenAjax object?

},
bim: function () {
alert("Bim!");
}
});

And similarly for DOM events like "click".

Thanks,
/Patrick

Jeremy Kahn

unread,
Sep 30, 2010, 12:10:32 PM9/30/10
to javasc...@googlegroups.com
Hi Patrick,

This is what I would do:

$.Controller.extend('Foo',{},
{
   init: function(){
      OpenAjax.hub.subscribe('myevent.bar.**', this.callback('bim'));
   },

   bim: function () {
       alert("Bim!");
   }
});

-------------------

Using the "this.callback()" function will retain a reference to the controller, and should work the way you expect.  Here's the API documentation:  http://v3.javascriptmvc.com/index.html#&who=jQuery.Class.prototype.callback

Hope this helps.


--
You received this message because you are subscribed to the Google Groups "JavaScriptMVC" group.
To post to this group, send email to javasc...@googlegroups.com.
To unsubscribe from this group, send email to javascriptmv...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/javascriptmvc?hl=en.




--
Jeremy Kahn
Twitter:  @jeremyckahn

Michael Mayer

unread,
Sep 30, 2010, 12:11:24 PM9/30/10
to javasc...@googlegroups.com
Hello Patrick,

normally you can just use "this" in all the actions. If you want to
access a "static" action from the prototype then you need to use
this.Class.bim(). If you work with callbacks, use this.callback():

'.element click': function () {
$.ajax({success: this.callback('foo')});
},

foo: function () {
this.bar();
},

bar: function () {
}

Michael

2010/9/30 PatrickR <patrick...@gmail.com>:

> --
> You received this message because you are subscribed to the Google Groups "JavaScriptMVC" group.
> To post to this group, send email to javasc...@googlegroups.com.
> To unsubscribe from this group, send email to javascriptmv...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/javascriptmvc?hl=en.
>
>

--
Phone:  +49-7071-1380380
Fax: +49-7071-1380389
Mobile: +49-171-2129566
Skype: nulldevice.de

Please consider the environment before printing this email.

Justin Meyer

unread,
Sep 30, 2010, 12:18:17 PM9/30/10
to javasc...@googlegroups.com
I don't think it matters but what version are you using?  Despite what Jeremy showed, you can subscribe directly with controller method names.  The code below should work:

$.Controller.extend('Foo',{},
{
   'myevent.bar.** subscribe': function(topic, data) {
       this.bim(); 

},
   bim: function () {
       alert("Bim!");
   }
});


$("#foo").foo();
OpenAjax.hub.publish("myevent.bar.foo")

If this doesn't work for you, I'm very surprised, but please let me know.  It's a bug and I will have to check it out.

Justin Meyer

unread,
Sep 30, 2010, 12:25:18 PM9/30/10
to javasc...@googlegroups.com
Also, Jeremy's suggestion wouldn't unsubscribe the subscription if the controller's element is removed from the page.  This could likely lead to errors.


Justin Meyer

Jupiter Consulting
\Development\Training\Support
847-924-6039
justin...@gmail.com

Johannes Nel

unread,
Sep 30, 2010, 12:31:04 PM9/30/10
to javasc...@googlegroups.com

doesn't this.callback create a function closure you are never deleting here?


basically 


var f = this.callback("otherFunction");


and at some point you would need to 

delete f;


otherwise you are leaving function pointers around and that means a mark and sweet garbage collector won't collect.

j:pn
\\no comment

Justin Meyer

unread,
Sep 30, 2010, 12:57:05 PM9/30/10
to javasc...@googlegroups.com
Johannes,
  You don't have to delete the callback.  And in reality it wouldn't work even if you tried.  A few things about delete and JS memory.

First, try running:

(function(){
  var a = 1;
  console.log(delete a);
  console.log(a)
})()

You'll get 
> false
> 1

You can't delete variables, with 1 exception - some JS interpreters allow delete to work if "var a" was declared in the global scope, some (like Rhino) do don't.

Once declared, variables exist in in their scope forever.

The delete statement really just returns IF javascript can remove a reference, not if there was a reference to return.  This is why:

var a = {b: 'c'}
console.log(delete a.b)
console.log(delete a.b)

returns true twice.

Finally, the real problem with Jeremy's example isn't something that delete would fix.  Delete just removes references.  For practically all purposes, it's the same as doing:

a.b = undefined;

The problem is that OpenAjax.hub has a reference to the callback function returned by callback.  So even if you could do something like:

var cb = this.callback('foo')
OpenAjax.hub.subscribe("bar", cb);
delete cb

and cb would be set to undefined.  OpenAjax would still have a reference pointing to cb.  This is why you subscribe in 'Action' form:

"foo.bar subscribe" : function( ... ) { ... }

JavaScriptMVC will do the unbinding for you.

If you wanted to do this yourself, you could do:
init : function(){
  this.subscription = OpenAjax.hub.subscribe("foo.bar", this.callback('something') )
},
destroy : function(){
  OpenAjax.hub.unsubscribe(this.subscription)
  this._super();
}

Justin Meyer

Jupiter Consulting
\Development\Training\Support
847-924-6039
justin...@gmail.com


Johannes Nel

unread,
Sep 30, 2010, 7:42:12 PM9/30/10
to javasc...@googlegroups.com
what does this mean
JavaScriptMVC will do the unbinding for you.

make it clear.

Justin Meyer

unread,
Sep 30, 2010, 7:53:31 PM9/30/10
to javasc...@googlegroups.com
When you use controller to subscribe to an action like:

"foo.bar subscribe" : function(called, data){

}

Controller keeps track of this subscription.  When the controller is destroyed (by it's element being removed, or calling destroy directly on the controller), it goes through all of its events and unbinds them and through all of its subscriptions and unsubscribes them.

This is one of the best parts about controller.  You can remove them very cleanly.

Justin Meyer

Jupiter Consulting
\Development\Training\Support
847-924-6039
justin...@gmail.com


Johannes Nel

unread,
Sep 30, 2010, 8:04:49 PM9/30/10
to javasc...@googlegroups.com
ok, so i undertand what your code does. but how is this different from deleting or setting referencers to null or undefined? 
What I am asking is what your code does what I am missing in my general approach. 
Basically, i create function pointers on public class scope - in long hand the code would look like this.

p : function ()
{
var me = this;
this.funcPointer = function (..)
{
me.callSomeFunc()
}
}

someFunc : function ()
{
delete this.funcPointer;

}

this approach i am pretty certain will never leak me memory, but then again, i seem to be learning things about this language the whole time.

as a side note, there is no point deleting local function memory in javascript or any other prototyped language, i get that, variables exist for the whole time in the scope you declared them in, i should have made my example a bit more javascript correct instead of just putting code out there with a concept. my bad.

what does your framework do which makes certain these function pointers get deleted other than what i said here. when you say it unbinds, do you mean it sets the function pointer to null afterwords?

where in your framework can i see the code you are talking about?

PatrickR

unread,
Oct 1, 2010, 5:47:31 AM10/1/10
to JavaScriptMVC
That's it! I had forgot about the this.callback('foo') and just used
this.foo so i got the wrong scope of "this" in the callback.

Thanks,
/Patrick

On Sep 30, 6:11 pm, Michael Mayer <google.b...@liquidbytes.net> wrote:
> Hello Patrick,
>
> normally you can just use "this" in all the actions. If you want to
> access a "static" action from the prototype then you need to use
> this.Class.bim(). If you work with callbacks, use this.callback():
>
> '.element click': function () {
>   $.ajax({success: this.callback('foo')});
>
> },
>
> foo: function () {
>   this.bar();
>
> },
>
> bar: function () {
>
> }
>
> Michael
>
> 2010/9/30 PatrickR <patrick.run...@gmail.com>:
>
>
>
>
>
> > Hi,
>
> > I have a controller Foo and in it an OpenAjax event callback
> > myevent.bar(topic, data) and another function bim(). How do I within
> > the callback get the controller scope from within the callback bar to
> > call bim()?
>
> > $.Controller.extend('Foo',{},
> > {
> >    'myevent.bar.** subscribe': function(topic, data) {
> >        var me = $("#foo").controllers()[0]; // what i do now. Is
> > there a better way?
> >        me.bim();
>
> >        this.bim(); // won't work. this is the OpenAjax object?
>
> > },
> >    bim: function () {
> >        alert("Bim!");
> >    }
> > });
>
> > And similarly for DOM events like "click".
>
> > Thanks,
> > /Patrick
>
> > --
> > You received this message because you are subscribed to the Google Groups "JavaScriptMVC" group.
> > To post to this group, send email to javasc...@googlegroups.com.
> > To unsubscribe from this group, send email to javascriptmv...@googlegroups.com.
> > For more options, visit this group athttp://groups.google.com/group/javascriptmvc?hl=en.

Justin Meyer

unread,
Oct 1, 2010, 10:55:46 AM10/1/10
to javasc...@googlegroups.com
I don't have time to walk you through the code, there's too many layers.

But, I can explain it with addEventListener as a substitute.

If you do:

var thing = {myFunc : function(){
  alert('clicked')
}}

document.addEventListener('click',thing.myFunc,false)

delete thing.myFunc

And click the document, you will still see a click.  Delete removes references not the actual memory.

To remove the click handler you have to:

document.removeEventListener('click',thing.myFunc,false)

Justin Meyer

Jupiter Consulting
\Development\Training\Support
847-924-6039
justin...@gmail.com


Johannes Nel

unread,
Oct 1, 2010, 2:59:38 PM10/1/10
to javasc...@googlegroups.com
i have done my tests and my approach seems fine.
can you point me to where in the code you do what you are talking about, i need to see what you guys are doing, and the structure of how things are done in general in javascript i still find weird. give me a class name, let me inspect it.]

what do you use to profile memory?

Justin Meyer

unread,
Oct 1, 2010, 3:16:30 PM10/1/10
to javasc...@googlegroups.com
Controller's prototype setup and destroy methods.


You aren't testing with an 'event' bus.  Did you try seeing what happens with addEventListener?  You can do the same with open ajax:




Justin Meyer

Jupiter Consulting
\Development\Training\Support
847-924-6039
justin...@gmail.com

var thing = {myFunc : function(){
  alert('message')
}}

OpenAjax.hub.subscribe('message',thing.myFunc)

delete thing.myFunc
OpenAjax.hub.publish('message',thing.myFunc)

you will get a message.  delete only removes references, not the actual function

Reply all
Reply to author
Forward
0 new messages