Reputation: 601
Currently building a microservice application. The communication between each container is via web sockets and the gateway is a REST gateway.
I want to be able to use emit from within a post request, which is working fine as of right now. But when the the socket is to handle a on
event and then reply back via the gateway using a express response object, that object is not closed with a response.json
call. The object is still alive inside another on
event inside the same route, which then makes the new request generate the error, headers cannot be set after they are send
. This makes sense, but how do I ensure that the new request, gets a new response object ?
First request
gateway -> (ws) -> microserver -> (ws) -> gateway -> (http) user
Second request
gateway -> (ws) -> microserver -> (ws) -> gateway -> ERROR
Gateway snippet:
app.post("/api/user/create", function (req, res) {
console.log("Create request");
let token = req.get("Authentication");
let userData = req.body;
ioClientUsers.emit("create", {
"token": token,
"userData": userData
});
ioClientUsers.once("user created", success => {
console.log(res.headersSent);
if (success) {
return res.json({
"status": "created"
});
} else {
return res.json({
"status": "not created"
});
}
});
ioClientUsers.once("user not created", () => {
console.log(res.headersSent);
res.json({
"status": "not created"
});
});
});
Microservice snippet
socket.on("create", createObj => {
console.log(createObj);
userController.createUser(createObj.token, createObj.userData, (err, success) => {
console.log(err, success);
if (err) {
socket.emit("user not created");
} else {
socket.emit("user created", success);
}
});
});
EDIT Just posting again, so that if anybody else has the same problem, either the one answer to this or this edit solves the problem:
app.post("/api/user/create", function (req, res) {
let token = req.get("Authentication");
let userData = req.body;
ioClientUsers.emit("create", {
"token": token,
"userData": userData
});
ioClientUsers.once("user created", userCreated);
ioClientUsers.once("user not created", userNotCreated);
function userCreated(success){
if (success) {
res.json({
"status": "created"
});
} else {
res.json({
"status": "not created"
});
}
rmListner();
}
function userNotCreated(){
console.log(res.headersSent);
res.json({
"status": "not created"
});
rmListner();
}
function rmListener(){
ioClientUsers.removeListener("user created", userCreated);
ioClientUsers.removeListener("user not created", userNotCreated);
}
});
Upvotes: 0
Views: 301
Reputation: 13902
I'd do something like this
app.post("/api/user/create", function (req, res) {
console.log("Create request");
let token = req.get("Authentication");
let userData = req.body;
ioClientUsers.emit("create", {
"token": token,
"userData": userData
});
function createdCallback(success) {
if (success) {
sendStatus('created')
} else {
sendStatus('not created')
}
}
function notCreatedCallback() {
sendStatus('not created')
}
function sendStatus(status) {
console.log(res.headersSent);
// UNSUBSCRIBE YOUR LISTENERS HERE
ioClientUsers.removeListener("user created", createdCallback);
ioClientUsers.removeListener("user not created", notCreatedCallback);
res.json({'status': status})
}
ioClientUsers.once("user created", createdCallback);
ioClientUsers.once("user not created", notCreatedCallback);
});
The socket listeners are all removed before res.json
is called. See if that works.
Upvotes: 1