2

I have the following block of code:

async.parallel([
    function(cb){ module.rpc("user.data",{"username":data.username},cb); },
    function(cb){ module.rpc("group.list",{"username":data.username},cb); },
    function(cb){ module.rpc("set.list",{},cb); }
],function(error,result){
    if(error){ callback(error); return; }
    var user = result[0], groups = result[1], sets = result[2];
    callback(null,template.render({"user":user,"groups":groups,"sets":sets}));
});

module.rpc is a function that fetches the necessary data from the server via socket.io. Now, the final function (async.parallel's second argument) is supposed to be called only after the given 3 functions have called-back. However, during the template (EJS) rendering, when I try to access groups.data, I sometimes get the error:

Uncaught TypeError: Cannot read property 'data' of undefined

The code seems perfectly fine to me, but works only occasionally. I have reloaded the page repeatedly, without changing the underlying code, and had a success rate of about 20%. I have absolutely no clue why things are going wrong here. All I can guess is that the assignment of that variable is delayed. And so I tried delaying the rendering using window.setTimeout, but to no avail. Why is this happening? How do I fix it?

Uli Köhler
  • 13,012
  • 16
  • 70
  • 120
Kaustubh Karkare
  • 1,083
  • 9
  • 25
  • *Where* do you access `groups.data`? Please include the relevant code. And what does `result` look like, does `module.rpc` always return data? – Bergi Feb 09 '13 at 14:04
  • I could, but that code contains functions which I'd then need to explain. However, if I put a `console.log(result);` statement in the final function, the 1-line summary of the object (in Chrome Console) says that there are 2 objects in the array, but when I expand it, it shows 3. If I specifically try `console.log(result[1]);`, it says `undefined` corresponding to the above failures. – Kaustubh Karkare Feb 09 '13 at 14:09
  • Hm, that sounds like your `async.parallel` failed. – Bergi Feb 09 '13 at 14:19
  • I'm not sure how that could happen. And that too only occasionally. – Kaustubh Karkare Feb 09 '13 at 14:33
  • 1
    Alright, so I found the problem. `socket.io` keeps sending events to the server repeatedly until it gets an acknowledgement. Depending on the server load, acknowledgements might not be immediate. So multiple identical requests were being sent, and since async parallel uses a counter instead of individually tracking each function, the final function was getting prematurely called. – Kaustubh Karkare Feb 09 '13 at 15:12
  • Good call. Make it an answer so other people can learn from it :-) – Bergi Feb 09 '13 at 15:15

1 Answers1

2

socket.io keeps sending events to the server repeatedly until it gets an acknowledgement. Depending on the server load, acknowledgements might not be immediate. So multiple identical requests were being sent, and since async.parallel uses a counter instead of individually tracking each function, the final function was getting prematurely called.

Uli Köhler
  • 13,012
  • 16
  • 70
  • 120
Kaustubh Karkare
  • 1,083
  • 9
  • 25