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); }
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!
Does this pattern work in DWR version 2 ?
I can’t see why it wouldn’t – it’s not specifically a DWR thing, more Javascript + Async calls
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
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
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
}