views:

220

answers:

1

I'm trying to write a somewhat generic method for retrieving data either from the browser cache if it's available, or a JSON request if it's not. Right now, all I want to do is be able to give my data.get method an id, and return the correct results. This works perfectly fine - console logs the new object being retrieved via JSON the first time, and from memory the second time, but if you run this code you'll notice the blank object is returned a millisecond before the JSON, so it doesn't quite work as expected. I've tried setting intervals and callbacks and everything, but I can't figure out how to make it more synchronous. I feel like my fundamental assumption is wrong. I'm a newbie to OOP javascript. Also, I'm using jQuery for the json request. You can't just return the object in the callback of the getJson function either, since the other one will execute first.

Here is the contents of get.json:

{ "id" : 1, "name" : "hello" }

and the script/markup:

var entries = [];

       function Data(){}
       Data.prototype.get = function(id){
            var object = {}, length = entries.length, success = false;
            for (var i = 0; i < length; i++) {
                if (entries[i].id == id) {
                    object = entries[i];
                    i = length;
                    console.log("From browser: " + object.name);
                    success = true;
                }
            }
            if (success == false) {
                $.getJSON("get.json", function(data){
                    entries.push(data);
                    object = data;
                    console.log("Newly fetched: " + object.name);
                });
            }
            return object;
        }

        $(function(){
            var data = new Data();
   data.get(1);
            console.log((data.get(1).name);
        });
+1  A: 

I would use a callback. If the data exists in the browser cache, the callback will be fired immediately. If not, it will be fired when the Asynchronous request finishes.

function Data(){}
Data.prototype.get = function(id, callback){
     var object = {}, length = entries.length, false;
     for (var i = 0; i < length; i++) {
         if (entries[i].id == id) {
             object = entries[i];
             console.log("From browser: " + object.name);
             callback(object);
             return; // Don't let execution continue
         }
     }

     $.getJSON("get.json", function(data){
         entries.push(data);
         object = data;
         console.log("Newly fetched: " + object.name);
   callback(object);
     });
 }

 $(function(){
     var data = new Data();
     data.get(1, function(obj){
  console.log(obj.name);
  });
 });

Another way would to be to make your AJAX call synchronous which would pause all execution, but that is a very bad idea.

Edit: I also changed your code a little to remove the success variable, and chose to return right from the for loop (thereby breaking the loop).

Doug Neiner
Thank you, this was just the trick! Brilliant. It's a whole different way of thinking that I need to train myself for. Thanks again.
Vibhu
No problem. Thinking asynchronously is a major shift in thinking. Every time I work on a project that uses it, I have to stop and think for a bit!
Doug Neiner