I have a question regarding the behaviour of recursive async requests in Node.js.
The function below is intended to return search results from MongoDB. If the initial search results come up empty, I split the text into individual words and then attempt to recursively fetchResult(...) for each word, passing on the res object as a parameter.
function fetchResult(text, res){
var MongoClient = require('mongodb').MongoClient;
MongoClient.connect(mongoURL + "/search", function (err, db) {
if(err) throw err;
db.collection('results', function(err, collection) {
// search for match that "begins with" text
collection.findOne({'text':new RegExp('^' + text, 'i')}, function(err, items){
var result = (items == null || items.result == null) ? "" : items;
if (result){
res.send(result);
}
else {
// no result, so fire off individual word queries - if any spaces found
if (text.indexOf(' ') > -1){
// split string into array
var textArray = text.split(" ");
// recursively process individual words
for (index = 0; index < textArray.length; index++) {
// ***** RACE CONDITION HERE? *****
fetchResult(textArray[index], res);
}
}
else {
// just return empty result
res.send(result);
}
}
});
});
});
}
I suspected this might cause a bit of a race condition, as the reference to res fans out asynchronously, and this was confirmed when I ran the code and observed the following error:
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:344:11)
So my question is: How can I achieve the desired recursive behaviour of executing individual string queries in sequence, returning only when we find the first result (or at the end of the process when search returned no results at all)?