Reputation: 2143
I want my http server to return some json returned from a async function. I've managed to make it work, but it only works once, then it throws: "Can't set headers after they are sent." error.
here is the following code:
var server = restify.createServer();
server.get('/', function(req, res, next) {
feed("dilma",[]);
eventEmitter.on('retorno', function(retorno){
res.send(retorno);
});
});
server.on("listening", function() {
console.log("server running!");
});
server.listen(7171);
feed function:
var feed = function headLinesBySite(word, l) {
if (!Array.isArray(l)) {
console.log("por favor passe um array");
return false;
}
if (l !== []) {
links = l;
}
links = ["http://www.estadao.com.br/", "http://atarde.uol.com.br/"];
var teste = 0;
var final = [];
for (i = links.length - 1; i >= 0; i--) {
findHeadlines(links[i], word.toLowerCase(), function(r, url) {
final.push({
url: url,
manchetes: r
});
//console.log(url+" - "+r);
teste++;
console.log((teste / links.length) * 100 + "%");
if (teste === links.length) {
console.log("Concluído!");
console.log(final);
eventEmitter.emit('retorno', final);
}
});
}
};
findHeadlines function:
var findHeadlines = function findHeadlines(url, word, cb) {
request(url, {
timeout: 1000
}, function(error, response, body) {
if (!error && response.statusCode == 200) {
$ = cheerio.load(body);
texto = [];
var retorno = [];
b = $('body').text().toLowerCase();
c = b.replace(/\s+/g, ' ');
texto = c.split("¬");
for (var i = texto.length - 1; i >= 0; i--) {
if (texto[i].search(word) !== -1 && texto[i].length < 100) {
//console.log(texto[i]);
retorno.push("+" + texto[i] + "+");
}
}
cb(retorno, url);
} else {
console.log(error);
cb([], url);
}
});
};
The first time I call localhost/7171 I get the info, but after that, any GET request throws : "Can't set headers after they are sent.". I've read some similar questions about this same error but none of them helped me fix it... I just want to make the GET request wait for the async return of the feed function... Appreciate any help.
Upvotes: 2
Views: 62
Reputation: 150614
With
eventEmitter.on('retorno', function(retorno){
res.send(retorno);
});
you are subscribing to the retorno
event, but you never unsubscribe. Hence, if the event is raised a second time, the old route handler runs res.send
again - but now on an already closed connection.
Change on
to once
and the problem might be gone. For more details one would have to have a closer look at your entire code.
Hope this helps.
With subscribing and unsubscribing I mean that subscribing is like saying "From now on, I want to get notified when event X happens". This is valid until you say that you aren't interested any more (i.e., you unsubscribe). on
is the equivalent of subscribe
, usually you have to use removeListener
to unsubscribe
.
If you use once
, you are effectively saying that you are subscribing, but only until the event has happened a single time - and then you would like to unsubscribe automatically. That's why it works then :-)
Upvotes: 2