DWR Callback closures inside loops

I’ve been doing a fair bit of Javascript lately. Like anytime I learn a new language I look back at code I wrote a week ago and thing OMG… what was I thinking!?

One useful thing I learnt today was how to use the DWR closure callback pattern inside a loop.

My original code looked like this:


var taggedLinks = $$(".taggedlink");

for(var i=0; i < taggedlinks.length; i++) {
	RatingApi.getRating(taggedLinks[i].href, {
		callback: function(data) {
			displayRating(data, taggedLinks[i]);
		}
	});
}

Where RatingApi.getRating(..) is a DWR AJAX call. It’s fairly clear what the problem is: the displayRating function is called when RatingApi.getRating returns. Obviously the value of i will be not what was expected.

The solution looks like this (thanks Ben!):


var taggedLinks = $$(".taggedlink");

for(var i=0; i < taggedlinks.length; i++) {
	var remoteCall = {
		index : i,
		callback: function(data) {
			displayRating(data, taggedLinks[this.index]);
		}
	};	

	RatingApi.getRating(taggedLinks[i].href, remoteCall);
}

6 thoughts on “DWR Callback closures inside loops

  1. Yeah, I just discovered this pattern too, the dwr docs sort of hint at it, but in a fairly oblique manner, sufficiently so that you don’t feel like giving them any credit when you ‘discover’ this approach!

  2. I can’t see why it wouldn’t – it’s not specifically a DWR thing, more Javascript + Async calls

  3. Hi,

    In the following code, when I give an alert for ‘this.index’, it is displayed as undefined.

    Could you please help me.

    for(var i=0;i<ids.length;i++) {
    var remoteCall = {
    index : i,
    callback : function(data) {
    fillTable(data, ids[this.index]);
    }
    };
    PopulateParameterList.getAjaxPopulateParameterList(paramId,reportId,””,remoteCall);

    Thank you

  4. Lav,

    This approach doesn’t seem to work under pre v3.0 of DWR – I had the same problem – ie undefined index.

    After lots & lots of searching I eventually got it working by adapting Example 7 so that it would work from within a loop. (BTW: it also explains why the above approach doesnt work in Example 5)

    See: http://blog.morrisjohns.com/javascript_closures_for_dummies.html

    I hope someone finds this useful and it saves them some time.

    Paul

  5. Here is roughly how i got the looping callback to work… (this is specifically for dwr2.*)

    function newClosure(someNum, someRef) {
    return function(x) {
    showResultsInBrowser(x, someNum);
    }
    }

    function getServerResponses(){
    // some other stuff…
    var count = aJsVariableSomewhere;
    for(var k=1;k<=count;k++){
    closure = newClosure(k, {somevar : ‘closure’+k});
    remote.method(“response”+k, closure);
    }
    }

    function showResultsInBrowser(serverResponse, index){
    // do some UI stuff
    }

Leave a Reply

Your email address will not be published. Required fields are marked *