1

I am having some trouble working with oo javascript. I am creating a new object public and private methods. Now when I am calling the public method, it cannot access the private variable.

I believe I should return the public methods ( the internet ) but dont really know why. Can someone please explain what I am missing?

function something(){
    var somePanel;  // it is a jquery object to a div

    var createWindow = function(data){
        random.xhr('/chat', 'GET', null, function(res){
            var Container = $("#Container");
            somePanel = $("<div/>").addClass('somePanel').append(res);
            Container.append(somePanel.hide());
        });     
    };

    this.activate = function(){
        somePanel.show().siblings().hide();
    };

    this.init = function(data, fn){
        createWindow(data);
    };
};


connections[data] = new something();  // creates a new something object
connections[data].init(data);   //  which creates just a div object, actually
connections[data].activate();  // has code to show this panel and hide every other panel

When I call the activate() method, it cannot find somePanel. What should I be doing differently? And why?

amit
  • 10,133
  • 22
  • 72
  • 121
  • 1
    how do you define `somePanel` and where? try to explain it a bit more – Abu Romaïssae Oct 26 '13 at 17:42
  • 1
    this code runs perfectly good; you are not showing us the not working part. But I guess you used `var` somewhere hiding your original `somePanel` from `something` – Adassko Oct 26 '13 at 17:43
  • Also, what is the unused "that" argument for in the activate method? Also, somePanel isn't defined, so I'm guessing you're seeing Uncaught TypeError exceptions due to the value being undefined, no? – jamesmortensen Oct 26 '13 at 17:45
  • 1
    updated with some comments of the code – amit Oct 26 '13 at 18:02
  • I think you need to pass the reference to the somePanel variable, because your closure just declares the variable but never gets set, something like this should work: this.init = function( data, fnc, ref ){ /* your init code */ somePanel = ref; } – Sam Ccp Oct 26 '13 at 18:08
  • updated with some more code.. – amit Oct 26 '13 at 18:17
  • possible duplicate of [How to return the response from an AJAX call?](http://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-ajax-call) – user229044 Oct 26 '13 at 18:22
  • Ok, now with more code the problem is another one, the ajax call is asynch, which means that it is still being executed when the next method from your object is called, you need to provide some callbacks for keeping the workflow correctly. @meagar beat me to the example :D – Sam Ccp Oct 26 '13 at 18:26

2 Answers2

3

Classic problem with asynchronous methods.

You're xhr handler will not have been invoked when you run activate. You need to wait for your xhr handler to run, and then, in a callback, invoke activate.

Something along these lines:

// ...

this.init = function(data, fn){
    createWindow(data, fn);
};

var createWindow = function(data, fn) {
    random.xhr('/chat', 'GET', null, function(res){
        var Container = $("#Container");
        somePanel = $("<div/>").addClass('somePanel').append(res);
        Container.append(somePanel.hide());
        fn();
    });     
};

// ...

connections[data] = new something();
connections[data].init(data, function () { connections[data].activate() });
user229044
  • 232,980
  • 40
  • 330
  • 338
0

you're setting somePanel in the callback to an async call. You can't be guaranteed somePanel is set by the time you call activate().

edit meagar's answer is the best option from an OO perspective. The rest of my answer is aimed at maintaining the readability you're trying to achieve.

You may want to look into using a module that allows for asynchronous chaining (like async) or promises

Joseph Yaduvanshi
  • 20,241
  • 5
  • 61
  • 69