[英]How to solve nodejs uncaughtException: Connection already released error and MaxListenersExceededWarning?
I am building an express server to receive request (a dict with 10 items) from my react front end and then save the data to database.我正在构建一个快速服务器以从我的 React 前端接收请求(一个包含 10 个项目的字典),然后将数据保存到数据库中。 Below is my code.
下面是我的代码。 I found that my code is work and the query does save the record back to Db.
我发现我的代码可以正常工作,并且查询确实将记录保存回 Db。 But in each for loop, this error is returned in server.
但是在每个 for 循环中,这个错误都会在 server.js 中返回。 What cause this error and the MaxListenersExceededWarning?
是什么导致此错误和 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
One connection ( conn
) is being retrieved from the pool, and is used to launch 10 queries in the forEach
loop.正在从池中检索一个连接 (
conn
),并用于在forEach
循环中启动 10 个查询。
When the first query finishes to run, the first step of its callback is: conn.release()
.当第一个查询完成运行时,其回调的第一步是:
conn.release()
。 The connection is released.连接被释放。
When the second query finishes to run, its callback also tries to release the connection,causing the error.当第二个查询完成运行时,其回调也尝试释放连接,从而导致错误。
This problem might be solved in multiple ways:这个问题可以通过多种方式解决:
In the callback of the database query, before calling call.release
, check the number of queries already processed, and only close the connection when the last product is being processed.在数据库查询的回调中,在调用
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)
}
});
});
Edit : There is also an issue with the res.json
calls: inside the code in the question, res.json({ success: true })
is always executed, without waiting for the queries' execution results.编辑:
res.json
调用也有一个问题:在问题的代码中, res.json({ success: true })
总是被执行,而不等待查询的执行结果。 The modified code sample above calls res.json
only once after the execution of all queries, this is the only place where res.json
should be called.上面修改的代码示例在所有查询执行后只调用
res.json
一次,这是唯一应该调用res.json
地方。 This implies modifying the client-side code so that it can handle an array of errors, rather than only one error.这意味着修改客户端代码,以便它可以处理一系列错误,而不仅仅是一个错误。
It is not a good practice to use for
loops for the execution of asynchronous code.使用
for
循环来执行异步代码不是一个好习惯。 You might run into Maximum call stack size exceeded
errors whenever the data volume gets too large.每当数据量变得太大时,您可能会遇到
Maximum call stack size exceeded
错误。
Instead, create a recursive function (eg updateDictItem
) to process one update query at a time.相反,创建一个递归函数(例如
updateDictItem
)以一次处理一个更新查询。 Read more about the asynchronous patterns in node.js in this article .在 本文中阅读有关 node.js 中异步模式的更多信息。
Rather than firing ten database queries, it is worth considering grouping all the updates in one MERGE
update statement , otherwise doing all the updates in a TRANSACTION
.与其触发十个数据库查询,不如考虑将所有更新分组在一个
MERGE
更新语句中,否则在TRANSACTION
进行所有更新。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.