views:

217

answers:

2

I'm trying to assign some JSON data to a property of a JS.Class instance.

var MyClass = new JS.Class({
  initialize: function(uuid) {
      this.uuid = uuid;
  },
  write: function() {
    $.getJSON(url+"?callback=?", {}, function(data) {
      Assign(data);
    });
    function Assign(data) { this.content = data; };
  }
});

var m = new MyClass("uuid_goes_here");
m.write();

The JSON is received asynchronously, which is why there's a function call within the $.getJSON callback.

The problem I have now is that the this.content within the Assign function is not within the scope of the instance method named write. So whereas this.uuid returns correctly, this.content remains undefined (as you would expect).

Any ideas on how to correct this? I've tried using a global variable as a workaround but the async call doesn't allow for that (plus it's a crappy solution).

Some points to note, in case they matter: I have to use JSONP, so the "?callback=?" has to stay, and I'd like to keep it async.

A: 

You should cache the current instance in the write method and update it after ajax.

write: function() {
  var self=this;
 $.getJSON(url+"?callback=?", {}, function(data) {
    self.data=data;
 });
}
czarchaic
Doesn't that essentially achieve the same thing as Pascal MARTIN's answer? I've tried it out and it works, but only in as much as working right after the ajax call and never again. I eventually want to use this.content within other instance methods besides write, like I can with this.uuid.
joecorcoran
+4  A: 

I would usually go for either czarchaic's version, or replace Accept with a bound method from the object. What you have to bear in mind is that calling Accept() like that (as a function call rather than a method call) will bind this to the global object, i.e. window. I'd try this:

var MyClass = new JS.Class({
  initialize: function(uuid) {
      this.uuid = uuid;
  },
  write: function() {
    $.getJSON(url+"?callback=?", {}, this.method('setContent'));
  },
  setContent: function(data) {
    this.content = data;
  }
});

See http://jsclass.jcoglan.com/binding.html for more info.

jcoglan
This worked perfectly, thanks! Had a feeling it'd be to do with binding but the right approach escaped me.
joecorcoran
Just as an addendum: despite jcoglan's solution working well, if I was planning on writing a new instance method which utilises this.content, and calling the new instance method directly after write(), the async nature of $.getJSON would screw that up too. Just wanted to make that clear.
joecorcoran