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. Below is my code. I found that conn.query
will only call the query of the last item which mean the same query is called 10 times. Only 1 record is updated. I want to use for loop is because I want to get the err msg if any item is not saved successfully. So I don't want to put all 10 items in one UPDATE query
. How can I solve this problem?
The request data:
{{.....}, {.....}, {.....}, {.....}, {.....}} #10 item
Code:
router.post('/fruit', (req, res) => {
var err_list = [];
for (let r in req.body) {
#for-loop here is used to put each r into query
query = "UPDATE ........."
console.log(query) #output 10 queries with different params
getConnection(function(err, conn){
if (err) {
return res.json({ success: false, error: err })
} else {
conn.query(query, function (err, result, fields) {
conn.release()
console.log(query, err) #output 10 same queries
if (err) {
err_list.push(err);
}
});
}
})
}
if (err_list.length === 0){
return res.json({ success: true });
} else {
return res.json({ success: false, data: err_list });
}
});
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
The reason why this is happening is that the query
variable is not declared anywhere. This should cause an error in strict mode (and you should activate it).
Now the behavior in your code is the following:
- Since
query
is not declared, it is implicitly declared asvar
. That means the scope is the surrounding arrow function - Since the scope is the surrounding arrow function, there is a single
query
variable for all of the loop iterations, then every iteration overrides this variable getConnection
is asynchronous. That means you are telling 10 times "open a connection later" and when the connections are open, the loop has already ended. EverygetConnection
callback can then access the singlequery
variable that contains the last query.
In short, in order to fix the code, declare query
as let query
so that it is scoped to the loop, and every loop iteration has its own query
variable. Also, prefer using strict mode in order to throw explicit errors when the code is dirty, and spend less time with problems like this.