[英]How to solve nodejs uncaughtException: Connection already released error and MaxListenersExceededWarning?
我正在构建一个快速服务器以从我的 React 前端接收请求(一个包含 10 个项目的字典),然后将数据保存到数据库中。 下面是我的代码。 我发现我的代码可以正常工作,并且查询确实将记录保存回 Db。 但是在每个 for 循环中,这个错误都会在 server.js 中返回。 是什么导致此错误和 MaxListenersExceededWarning?
The request data:
{{.....}, {.....}, {.....}, {.....}, {.....}} #10 item
Code:
connection.js:
const p = mysql.createPool({
"connectionLimit" : 100,
"host": "example.org",
"user": "test",
"password": "test",
"database": "test",
"multipleStatements": true
});
const getConnection = function(callback) {
p.getConnection(function(err, connection) {
callback(err, connection)
})
};
module.exports = getConnection
routers.js
router.post('/test', (req, res) => {
getConnection(function(err, conn){
if (err) {
return res.json({ success: false, error: err })
} else {
const dict = req.body;
Object.keys(dict).forEach(function(r){
#putting dict's value to query
query = "UPDATE ......;"
conn.query(query, function (err, result, fields) {
conn.release()
console.log(query)
if (err) {
console.log("err")
return res.json({ success: false, error: err });
}
});
});
}
});
return res.json({ success: true });
});
Error:
error: uncaughtException: Connection already released
Error: Connection already released
at Pool.releaseConnection (/home/node_modules/mysql/lib/Pool.js:138:13)
at PoolConnection.release (/home/node_modules/mysql/lib/PoolConnection.js:35:15)
at Query.<anonymous> (/home/routes/test.js:276:22)
at Query.<anonymous> (/home/node_modules/mysql/lib/Connection.js:526:10)
at Query._callback (/home/node_modules/mysql/lib/Connection.js:488:16)
at Query.Sequence.end (/home/node_modules/mysql/lib/protocol/sequences/Sequence.js:83:24)
at Query._handleFinalResultPacket (/home//node_modules/mysql/lib/protocol/sequences/Query.js:149:8)
at Query.OkPacket (/home//node_modules/mysql/lib/protocol/sequences/Query.js:74:10)
at Protocol._parsePacket (/home//node_modules/mysql/lib/protocol/Protocol.js:291:23)
at Parser._parsePacket (/home//node_modules/mysql/lib/protocol/Parser.js:433:10)
(node:15881) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 finish listeners added. Use emitter.setMaxListeners() to increase limit
正在从池中检索一个连接 ( conn
),并用于在forEach
循环中启动 10 个查询。
当第一个查询完成运行时,其回调的第一步是: conn.release()
。 连接被释放。
当第二个查询完成运行时,其回调也尝试释放连接,从而导致错误。
这个问题可以通过多种方式解决:
在数据库查询的回调中,在调用call.release
之前,检查已经处理的查询数,只有在处理完最后一个产品时才关闭连接。
const dict = req.body;
// initialize counter
let itemCount = 0
, errors = []
Object.keys(dict).forEach(function(r){
#putting dict's value to query
query = "UPDATE ......;"
conn.query(query, function (err, result, fields) {
// check whether this is the last callback
if (itemCount === dict.length-1) {
conn.release()
let result = errors.length ? { success: false, error: errors } : { success: true }
res.json(result)
}
// increment counter
itemCount++
console.log(query)
if (err) {
console.log("err")
errors.push(err)
}
});
});
编辑: res.json
调用也有一个问题:在问题的代码中, res.json({ success: true })
总是被执行,而不等待查询的执行结果。 上面修改的代码示例在所有查询执行后只调用res.json
一次,这是唯一应该调用res.json
地方。 这意味着修改客户端代码,以便它可以处理一系列错误,而不仅仅是一个错误。
使用for
循环来执行异步代码不是一个好习惯。 每当数据量变得太大时,您可能会遇到Maximum call stack size exceeded
错误。
相反,创建一个递归函数(例如updateDictItem
)以一次处理一个更新查询。 在 本文中阅读有关 node.js 中异步模式的更多信息。
与其触发十个数据库查询,不如考虑将所有更新分组在一个MERGE
更新语句中,否则在TRANSACTION
进行所有更新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.