I'm implementing a functionality which should upon a click on a button extend an user session lifespan by sending a request to the backend and to update the database using MySQL2.
In order to do that I wrote the following front-end code:
onClose: function (oAction) {
try {
if (oAction == "YES") {
let reqURL = "/sessionExtend";
let reqData = {
session_id: sessionStorage.getItem("SessionId"),
user_id: sessionStorage.getItem("UserId")
};
let callbackOK = function (responseData) {
curr.onSuccessfulResponse(curr, responseData, "sessionExtendSuccess", "sessionExtendFail", "", false);
};
let callbackErr = function (responseData) {
curr.onErrorResponse(curr, responseData, "sessionExtendFail");
};
curr.performRequest(reqURL, reqData, callbackOK, callbackErr);
}
} catch (err) {
console.log(err);
MessageToast.show(sMsg);
}
}
The request is received by app.js, which establishes the database connection using MySQL2 and forwards the request to the DAL:
app.post("/sessionExtend", async function (req, res) {
let session_id = req.body.session_id;
let user_id = req.body.user_id;
let con = DAL.getConnection();
res.setHeader("Content-Type", "application/json");
try {
const response = await DAL.sessionExtend(con, session_id, user_id);
res.send(JSON.stringify({
"result": true,
"message": "session extended"
}));
} catch (e) {
res.send(JSON.stringify({
"result": false,
"message": "can not extend session"
}));
}
con.close();
});
The DAL module executes the SQL-query and should return the result either success or error:
sessionExtend: async function sessionExtend(con, session_id, user_id) {
con.connect(function (err) {
try {
if (err) throw err;
con.query(qryDict.SQL_QUERIES.setUpdateExtendSession, [session_id, user_id], function (err) {
let result;
if (err) {
result = JSON.stringify({
"result": false,
"message": "failure"
});
} else {
result = JSON.stringify({
"result": true,
"message": "success"
});
}
return result;
});
} catch (err) {
let result = JSON.stringify({
"result": false,
"message": err
});
return result;
}
});
},
The problem is that when I execute this code in debugger, I get an exception:
ERR_STREAM_WRITE_AFTER_END Error [ERR_STREAM_WRITE_AFTER_END]: write after end at Socket.Writable.write (_stream_writable.js:297:11) at Connection.write (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:226:17) at Connection.writePacket (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:271:12) at ClientHandshake.sendCredentials (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\commands\client_handshake.js:64:16) at ClientHandshake.handshakeInit (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\commands\client_handshake.js:137:12) at ClientHandshake.execute (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\commands\command.js:39:22) at Connection.handlePacket (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:417:32) at PacketParser.onPacket (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:75:12) at PacketParser.executeStart (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\packet_parser.js:75:16) at Socket. (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:82:25)
I also paid attention that during the debugging, I firstly get on a frontend a response from the backend and only then I reach the breakpoints in DAL withing con.query(qryDict.SQL_QUERIES.setUpdateExtendSession, [session_id, user_id], function (err) {…}.
My questions:
Why do I get
ERR_STREAM_WRITE_AFTER_ENDand how to avoid it?Why do I firstly get on the frontend a response from the backend and only then I reach the breakpoints in DAL? I assumed that
await DAL.sessionExtend(con, session_id, user_id)should wait until the task on a DAL will be done and a promise will be resolved.
awaitit. Otherwise userequire('util').promisifyto turn it into one. - CherryDTDAL.getConnection(), which wraps thecreateConnection(…)of MySQL2, I'll checkrequire('util').promisify. Regardingcon.query(…), I use a callback, which should be reached when the query is done. - Mike