首页 > 解决方案 > 使用在 Node.js 上运行的 MySQL2 执行查询时出现 ERR_STREAM_WRITE_AFTER_END

问题描述

我正在实现一个功能,该功能应该在单击按钮时通过向后端发送请求并使用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;
        }
    });
},

问题是,当我在调试器中执行此代码时,出现异常:

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) 在 Socket。(C:\Users\User\IdeaProjects\TST\node_modules\mysql2\lib\connection.js:82:25)

我还注意到,在调试过程中,我首先在前端得到来自后端的响应,然后才到达 DAL withing 中的断点con.query(qryDict.SQL_QUERIES.setUpdateExtendSession, [session_id, user_id], function (err) {…}

我的问题:

  1. 为什么我会得到ERR_STREAM_WRITE_AFTER_END以及如何避免它?

  2. 为什么我首先在​​前端得到来自后端的响应,然后才到达 DAL 中的断点?我认为await DAL.sessionExtend(con, session_id, user_id)应该等到 DAL 上的任务完成并且承诺将得到解决。

标签: javascriptnode.jsasync-awaitdata-access-layermysql2

解决方案


在CherryDT的帮助下,通过切换到 MySQL2 的 ES7 async/ await-wrapper 版本解决了这个问题mysql2/promise

为了节省其他公众的时间,最终的现成代码:

应用程序.js

app.post("/sessionExtend", async function (req, res) {

    let session_id = req.body.session_id;
    let user_id = req.body.user_id;

    const con = await DAL.getConnection();

    res.setHeader("Content-Type", "application/json");

    const response = await DAL.sessionExtend(con, session_id, user_id);

    res.send(JSON.stringify({
        "result": response.result,
        "message": response.message
    }));

    await con.close();

});

DAL.js

sessionExtend: async function sessionExtend(con, session_id, user_id) {

    let result;

    const [rows, fields] = await con.execute(qryDict.SQL_QUERIES.setUpdateExtendSession, [session_id, user_id]);

    if (rows.warningStatus === 0) {
        result = {
            "result": true,
            "message": "session extended"
        };
    } else {
        result = {
            "result": false,
            "message": "session is not extended"
        };
    }

    return result;

},

如您所见,现在代码更易于理解和维护。

PS我的建议:使用async/ await,它们很棒,并尽量避免回调。


推荐阅读