Одно соединение (conn
) извлекается из пула и используется для запуска 10 запросов в forEach
l oop.
Когда первый запрос завершается, первый шаг его обратного вызова: 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
. Это подразумевает изменение кода на стороне клиента, чтобы он мог обрабатывать массив ошибок, а не только одну ошибку.
Решить с помощью рекурсивной функции вместо l oop.
Не рекомендуется использовать циклы for
для выполнения асинхронного кода. Вы можете столкнуться с ошибками Maximum call stack size exceeded
всякий раз, когда объем данных становится слишком большим.
Вместо этого создайте рекурсивную функцию (например, updateDictItem
) для обработки одного запроса на обновление за раз. Подробнее об асинхронных шаблонах см. В node.js в этой статье .
Другие возможные улучшения
Вместо того, чтобы запускать десять запросов к базе данных, стоит рассмотреть возможность группировки всех обновлений. в одном MERGE
операторе обновления , в противном случае выполняются все обновления в TRANSACTION
.