Lazy loading with asychronous calls – A design pattern proposal

When using regular OOP, it is often a good idea to retrieve the data as last as possible, only if and when it is needed. This what is called lazy loading.

class MyClass
{
    private ABigObject _myVar;
    public ABigObject MyVar
    {
        get
        {
            if(this._myVar == null)
            {
                // Do the needed heavy stuff to retrieve the data here
            }
            return this._myVar;
        }
    }
}

One good thing with Ajax is that it can retrieve data on demand. The not-so-good thing is that the http connection comes at a cost.
So, being lazy in loading data is quite a good idea.

The problem is that, because the http connection can take some time, we do not want to make synchronous calls.

So the following code won’t work:

var myObj = {
    myVar:null,
    getMyVar:function(){
    	var that = this;
 
        if(this._myVar == null){
            $.post(
                '/get_my_var.php',
                { },
                function(data){
                    that.myVar = data;
                },
                'json'
            );
        }
        return this.myVar;
    }
 
}

The JQuery $.post method is asynchronous. It does not wait to be completed to pass the hand to the next statement.
So when the “return” is executed, there is a high chance that the ajax call is not completed and that this.myVar contains null.

The first very naïve option would be to try to force the ajax call to behave as if it was synchronous. Putting a long-enough pause before the return should be enough to be get greater chances the variable is set before returning it.
This is, of course a very bad idea.

  • You cannot be sure the return will always be called once the data is retrieved. Maybe the user is using a 56K line shared with 100 other people
  • To get bigger chances to get the data, you need to overestimate the pause delay, meaning loosing a lot of time
  • Your users do not want to wait!

To sum up, there is a good reason why the Ajax calls are made asychronously.

Conclusion: We just cannot copy/paste our design pattern from the above C# example.

It is very probably not the ultimate solution, but what I came up with is something like this:

var myObj = {
	myVar:null,
	doWithMyVar:function(callback){
		callback = callback || function(){	};
 
		$.post(
			'/get_my_var.php',
			{	},
			function(data){
				that.myVar = data;
				callback(that.myVar);
			},
			'json'
		);
	}
};
 
// To echo my var:
myObj.doWithMyVar(function(var){ alert(var);	});

Basically, we are turning things upside down. Instead of calling a function to retrieve the data and then process it, we send to the function that retrieves the data the code to be executed with it.

More elegant solutions are more than welcome!

    • guillaume bataille
    • October 6th, 2009

    jamais pris le temps de voir comment est codé le keepalive ajax en général mais c’est rigolo de voir comment tu t’y prends :)

  1. No trackbacks yet.