I've got a very simple and straightforward API written in Node.js and Express that works just fine, but every now and then, the jQuery.post call will remain "Pending" (and eventually timeout). On the server side, I've monitored the request and result and it is logging a 200 response code with the appropriate data in ~40ms. No matter how many times I refresh the page (the data in the call is static, not based on inputs), the request completes successfully on the server, but hangs in the client. If I restart the node.js server script, all is well and normal function on the client is restored.
It ran smooth without a restart for the last 3 days, then about one hour after I restarted the script I had to do it again. Been fine now for the last 2 hours.
Any insight would be helpful. Thanks.
EDIT - Adding code This is the function that is hanging.
exports.getDistinct = function(req, res) {
var params = {
filter: function() {
var filter = getParams(req, 'filter');
if ( filter ) {
f = {};
for (var key in filter)
f[key] = { $in: filter[key] }
var search = getParams(req, 'search');
if ( search ) {
for (var key in search) {
f[key] = new RegExp(helper.escapeRegExp(search[key]),"gi");
}
}
return f;
} else {
// send error
send(req,res,{'error': 'no filter specified'}, 500);
}
}(),
field: function() {
var field = getParams(req, 'field');
if ( field ) return field;
else send(req,res,{'error': 'no field specified'}, 500);
}(),
};
//console.log(util.inspect(params,false, null));
db.results.distinct(
params.field,
params.filter,
function(err, results) {
if (err) send(req,res,err,500);
if (params.field == 'Title') {
var filtered = [];
db.testcases.find().sort( { _id: 1 } ,function(err, tcnames) {
if (err) send(req,res,err,500);
for (var i=0;i<results.length;++i) {
if (results[i].match(/^up/gi)) {
tcnames.filter( function(tc) {
if (tc._id == results[i]) filtered.push(tc);
});
}
}
filtered.sort(helper.compare);
send(req,res,filtered,200);
});
} else {
send(req,res,results,200);
}
}
);
}
And here is the code for the send function being used:
function send(req, res, data, status) {
var isJsonp = req.query.hasOwnProperty('callback');
if (!status) status = 200;
if (isJsonp) res.send(req.query['callback']+'('+JSON.stringify(data)+')', status);
else res.send(data, status);
}
EDIT just noticed this in httpd.conf and I have no idea if its relevant:
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
BrowserMatch "MS FrontPage" redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
BrowserMatch "^WebDAVFS/1.[0123]" redirect-carefully
BrowserMatch "^gnome-vfs/1.0" redirect-carefully
BrowserMatch "^XML Spy" redirect-carefully
BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully
So usually these symptoms mean your logic within your request handler has a branch that isn't properly terminated by responding to the request or omits a guard clause return statement. I think this is an error in your code, and there may be other cases:
if (err) send(req,res,err,500);
That's a bug. It will send a response but continue executing the remainder of the function, resulting in misbehavior. You want:
if (err){
return send(req,res,err,500);
}
I think that's your only bug, but it's a good idea to A) try to keep your logic small enough and simple enough to make it easy to visually confirm every branch terminates with an HTTP response and a return statement where appropriate and then B) when things necessarily get larger or more branchy, consider using return whenever you send a response as a defensive coding technique.