Reputation: 317
I am trying to work with an oauth library for javascript to fetch tweets . I have created an object that takes in the url for the twitter timeline to fetch and puts it in a column. The code is
lister=function(opts) {
this.setresource =lister.setresource;
this.config = lister.config;
this.config.resource = opts;
this.putTweet = lister.putTweet;
this.listerstrap = lister.listerstrap;
this.addStrip = lister.addStrip;
this.setTweets = lister.setTweets;
this.addTweets = lister.addTweets;
}
Now, if I create two new objects of lister ,
var l1 = new lister('user1'); //user1 and user2 refer to url of the timelines
l1.listerstrap();
var l2 = new lister('user2');
l2.listerstrap();
The listerstrap function is :
lister.listerstrap = function () {
this.addStrip().setresource().addTweets();
}
The problem happens in addTweets()
lister.addTweets = function () {
var _ = this;
oauth.get(twiapi + _.config.resource, function (res) {
_.setTweets(JSON.parse(res.text));
console.log(_.config.resource); // *
});
At * , the this (_) refers to the same (l2 instance) and hence the tweets from both resources are set into the same column when setTweets is called
Is this a closure problem ?
Edit: I am trying to set tweets into different columns based on the timeline or lists(as is done in say Tweetdeck , where there is a different column for each list). Though I get the tweets from both urls but they are set into the same column. _ contains the reference to the div element for each column I created in addStrip(). But somehow _ refers to the same instance in the callback . I want it to set the tweets into their respective columns
Upvotes: 0
Views: 177
Reputation: 76423
The problem isn't the addTweets
method, if you read my previous answer: forget about it.
The problem is this:
this.config = lister.config;
this.config.resource = opts;
your constructor assigns a reference to an object, the object itself is not copied. So by assigning a reference to an instance, and then changing the referenced object, you're changing the object that is referenced by all instances.
The quick fix would be to change this.config = lister.config;
to something like:
this.config = {foo: 'bar', something: 'else', resource: opts};//each time the constructor is called, create a new object literal
But please, do look into working with prototypes, because assigning references to properties of the function object, that also doubles as a constructor is not the best approach.
Update:
In response to the OP's comment: What you're seeing makes perfect sense. You're creating a new instance, setting the single config.resource
object (there is only one) to User1
, and the addTweets
function is invoked. This function performs an asynchronous request. Asynchronous is something that is all too often overlooked, but very important in this case: before the callback function (that uses the config.resource
value) is invoked, you create a new instance, and then the config.resource
property is changed. The callback function isn't invoked 'till after the second instance is constructed. That's why the config.resource
value is changed in that split second between calling addTweets
and the async callback being invoked, because that's when the second instance is created. It's as simple as that, really.
Upvotes: 1
Reputation: 153184
I'm pretty sure that the _
refers to different instances. The problem is that you're overwriting properties of the shared config object when you do this:
this.config = lister.config;
this.config.resource = opts;
So, your l1
and l2
always have the very same config
object. As soon as you instantiate l2
, it overwrites the resource
property.
You probably want to create a clone:
this.config = clone(lister.config);
where clone
may be some implementation of your choice.
Upvotes: 1