【发布时间】:2020-06-26 09:06:31
【问题描述】:
我正在实现一项功能,该功能应在单击按钮时通过向后端发送请求并使用 MySQL2 更新数据库来延长用户会话的生命周期。
为此,我编写了以下前端代码:
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);
}
}
请求被app.js接收,它使用MySQL2建立数据库连接并将请求转发给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();
});
DAL 模块执行 SQL 查询并应返回成功或错误的结果:
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;
}
});
},
问题是当我在调试器中执行这段代码时,我得到一个异常:
ERR_STREAM_WRITE_AFTER_END 错误 [ERR_STREAM_WRITE_AFTER_END]:写入 结束后 在 Socket.Writable.write (_stream_writable.js:297:11) 在 Connection.write (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:226:17) 在 Connection.writePacket (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:271:12) 在 ClientHandshake.sendCredentials (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\commands\client_handshake.js:64:16) 在 ClientHandshake.handshakeInit (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\commands\client_handshake.js:137:12) 在 ClientHandshake.execute (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\commands\command.js:39:22) 在 Connection.handlePacket (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:417:32) 在 PacketParser.onPacket (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:75:12) 在 PacketParser.executeStart (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\packet_parser.js:75:16) 在套接字。 (C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:82:25)
我还注意到,在调试过程中,我首先在前端得到来自后端的响应,然后才到达 DAL 中的断点 con.query(qryDict.SQL_QUERIES.setUpdateExtendSession, [session_id, user_id], function (err) {…}。
我的问题:
为什么我会得到
ERR_STREAM_WRITE_AFTER_END以及如何避免它?为什么我首先在前端得到来自后端的响应,然后才到达 DAL 中的断点?我假设
await DAL.sessionExtend(con, session_id, user_id)应该等到 DAL 上的任务完成并且承诺将得到解决。
【问题讨论】:
-
您不是在等待您的 con.connect 和 con.query 调用。如果您的 SQL 库有一个 Promise 接口,请使用该接口并
await它。否则使用require('util').promisify将其变成一个。 -
流结束后的写入发生是因为您在 con.query 甚至运行之前执行了 con.close。
-
@CherryDT,我假设与
DAL.getConnection()类似,它包装了 MySQL2 的createConnection(…),我会检查require('util').promisify。关于con.query(…),我用了一个回调,应该是查询完成就可以到达。 -
是的,但是您的 sessionExtend 函数早已在回调被执行时返回。请参阅下面的答案
-
糟糕,我现在才看到您指定使用的是 MySQL2。编辑我的答案。
标签: javascript node.js async-await data-access-layer mysql2