3

I'm new to javascript, and I found that I don't know an appropriate way to get an instance of the same variable repetedly. I am opening an Xml file with this:

function testXML(){
if (window.XMLHttpRequest)
  {// code for IE7+, Firefox, Chrome, Opera, Safari
  xmlhttp=new XMLHttpRequest();
  }
else
  {// code for IE6, IE5
  xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
  }
xmlhttp.open("GET","../res/data.xml",false);
xmlhttp.send();
xmlDoc=xmlhttp.responseXML;
return xmlDoc;
}

I added the return so I can pick that xml file and make some searches to load some lists with data. The problem is that each time I wanna take the xml file for reading some data I call this method, which does not only return me the xml, it alse does the IF/Else and openfile etc,etc... which I guess it's not that appropriate.

So how can I make a method that just returns me the xml file,so I can only open it once? Also, it's safe to open the xml file once and load it into a variable, let's say in index.html, and then navigate to other htmls without losing that variable value(the xml file) ?

Thanks!!

1
  • 2
    It's not a singleton pattern. You are asking about caching. Commented Feb 14, 2013 at 11:54

2 Answers 2

5
var xml;

function testXML(){
    if(!xml){
        if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari
            xmlhttp=new XMLHttpRequest();
        } else {// code for IE6, IE5
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
        xmlhttp.open("GET","../res/data.xml",false);
        xmlhttp.send();
        xml = xmlhttp.responseXML;
    }
    // return xml; // You can optionally also return the xml, but it'd be assigned to the variable already, any way.
}

Call that function once, and you can just use the xml variable.

Or, like suggested below, just use testXML() instead of the variable in your code, and un-comment the return.
This ensures you won't run into a undefined xml.

Sign up to request clarification or add additional context in comments.

3 Comments

Or you could go with textXML._xml = xml; to avoid accidental globals ( and then use return textXML._xml; ).
@Cerbrus if return xml; is optional, xml needs to be tested for undefined every time you want to use it, and if it is undefined then call testXML() before you use it. so i would alway call testXML() and use the returned object.
@t.niese: added a comment to the answer.
2

I would suggest you using the function closures in JavaScript to achieve this:

function createSingleton(fn) {
  var singleton = fn.apply(this);
  return function () {
    return singleton;
  };
}

This is a generic function that creates a singleton from any other function that returns something. It's result will be stored inside the function closure and you can execute the resulting function any number of times you like to get to the singleton. If you worry about passing that function around you can just store it in the global object:

var xml = createSingleton(getXML);

console.log(xml()); //use the xml object
console.log(xml() === xml());

What actually happens here is that createSingleton upon execution executes the underlying factory method once, stores it's result and gives you back a function that only returns that result. You can even do lazy loading with this:

function createSingletonLayz(fn) {
  var singleton = null,
      context = this;
  return function () {
    if (!singleton) {
       singleton = fn.apply(context)
    }
    return singleton;
  };
}

PS: Don't worry about multi-threading with the usual lock things to make the singleton code thread-safe. JavaScript only executes code in a single loop (that's why we have callback all over the place)

1 Comment

People don't realize that JavaScript is a functional language at the core and as such it can do really beautiful things very elegantly. If you are interested in this kind of thing I'd suggest you read Douglas Crockfords "JavaScript The Good Parts" book or watch some of his very entertaining talks over on his site.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.