Node.js Express API: How To Handle Multiple Callbacks
I have an API endpoint, which executes a function, which in turn listens to some events via a web socket and then throws the response of it back via a callback to the api endpoint, so the endpoint can respond with this object to a http request.
Sometimes I get only one event, sometimes I get two events from the listener. When only the first event appears, I have no problems. Because the second event has priority, I am using setTimeout
to wait for it, in case it still appears.
The problem ist, when the second event appears, my API endpoint responds with its object, but afterwards it crashes. I suppose it has something to do with the second callback and I don't know how to handle it. This is how the code is structured:
app.get('/api/myendpoint', function(req, res) {
myVar_1 = req.query.myvar1;
myVar_2 = req.query.myvar2;
myFunction(myVar_1, myVar_2, function(data, error) {
if (!error) res.json(data);
else res.json({"error": String(error)});
});
});
function myFunction(myVar_1, myVar_2, callback){
listenOnSocket.someEvent(myVar_1,
function(error, event) {
if (error) callback(null, error);
else setTimeout(function() {callback(event, null);}, 6000);
}
);
listenOnSocket.someEvent(myVar_2,
function(error, event) {
if (!error) callback(event, null);
else callback(null, error);
}
);
};
This is what my errors look like:
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Answer
Why its Happening?
1st
event occurs at which you set atimeout
for6000
ms to call the callback function.2nd
event occurs before6000
and the callback executes due to event2
. Response is sent here.timeout
completes and the pending function passed tosetTimeout
executes the callback which would send the response again and its not possible to send headers to a response after its sent.
Solution
A basic solution would be to check a flag variable in the function passed to set timeout that whether the 2nd
event has occured or not.
function myFunction(myVar_1, myVar_2, callback){
let executed = false;
listenOnSocket.someEvent(myVar_1,
function(error, event) {
if(!executed){
executed = true
if (error) callback(null, error);
else setTimeout(function() {
callback(event, null);
}, 6000);
}
}
);
listenOnSocket.someEvent(myVar_2,
function(error, event) {
if(!executed){
executed = true;
if (!error) callback(event, null);
else callback(null, error);
}
}
);
};
Related Questions
- → Maximum call stack exceeded when instantiating class inside of a module
- → Browserify api: how to pass advanced option to script
- → Node.js Passing object from server.js to external modules?
- → gulp-rename makes copies, but does not replace
- → requiring RX.js in node.js
- → Remove an ObjectId from an array of objectId
- → Can not connect to Redis
- → React: How to publish page on server using React-starter-kit
- → Express - better pattern for passing data between middleware functions
- → Can't get plotly + node.js to stream data coming through POST requests
- → IsGenerator implementation
- → Async/Await not waiting
- → (Socket.io on nodejs) Updating div with mysql data stops without showing error