Я использую node.js и express, также mysql. Я использую пул соединений для запроса соединений и создания обещания на нем, чтобы ограничить кошмар обратного вызова, следующий фрагмент установлен в файле, который я импортирую позже, обратите внимание, что я установил обработчик при error
чтобы не разорвать приложение в случае что-то действительно не так
exports.getConnection = () => {
return new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
reject('Could not obtain the connection from the pool: ${err}');
}
connection.on('error', err => {
console.log('SQL error (code: ${err.code}, message: ${err.sqlMessage}) while executing query: ${err.sql}');
});
resolve(connection);
});
});
};
И вот пример usecase (идея состоит в том, чтобы получить соединение, связать запрос в then
, и если произойдет не фатальная ошибка, я брошу его и обработаю выпуск соединения в обработчике catch
// Exception handler that release the connection then call the callback
function releaseConnectionHandler(err, connection, callback) {
connection.release();
callback(err, null);
}
exports.someRequest = function(ID, callback) {
sqlPool.getConnection().then(connection => {
connection.query("SELECT * from tableNotExists",
(err, result) => {
if (err) {
throw ({ err, connection, callback });
}
connection.release();
callback(null, result);
});
}).catch(({ err, connection, callback}) => releaseConnectionHandler(err, connection, callback));
};
Запрос не удастся, но я вижу, что обработчик даже не вызван (я вложил в него некоторый след...), и приложение завершается
node_modules/mysql/lib/protocol/Parser.js:80
throw err; // Rethrow non-MySQL errors
Правильное querie yoeld никаких проблем... Любые идеи, что я сделал неправильно при обработке ошибок?
Вы повторно бросаете ошибку, переданную на обратный вызов вашего запроса, которую библиотека, которую вы используете, затем повторно бросает, а также, наконец, неправильно попадает и обрабатывается в любом месте и приводит к ошибке. Вы не находитесь в контексте обещания при throw
, а в контексте функции обратного вызова, вызванной из модуля mysql
.
Вы также излишне смешиваете обещания и обратные вызовы, в частности функцию, которую вы экспортируете. Ваш вопрос указывает, что вы хотите отойти от обратных вызовов, поэтому я собираюсь основать этот ответ на этом показании.
Чтобы решить основную проблему, не бросайте ошибку. Вместо этого передайте его вызывающему:
const promisify = require("util").promisify;
exports.someRequest = function (ID) {
return sqlPool.getConnection().then(connection => {
return promisify(connection.query)("select * from tableNotExist")
.finally(connection.release);
});
};
Соединение всегда будет возвращено в пул, будь то успешное или с ошибкой. Затем вы можете вызвать метод с помощью:
yourModule.someRequest(id).then((results) => {
// Do something with the result set
}).catch((e) => {
// Handle error. Can be either a pool connection error or a query error.
});
Если у вас есть возможность использовать async/await
, код можно переписать:
const promisify = require("util").promisify;
exports.someRequest = async function (ID) {
let connection = await sqlPool.getConnection();
try {
return await promisify(connection.query)("select * from tableNotExist");
} finally {
connection.release();
}
};
Я также рекомендую использовать node-mysql2
поскольку у них есть API-интерфейс на основе Promise в дополнение к API-интерфейсу обратного вызова и, как мне кажется, улучшает производительность. Тогда вам не нужно писать эти утомительные обертки и вместо этого просто require('mysql2/promise')
и быть хорошим.
try{...} finally {...}
? Исходя из C ++, это кажется очень странным, я не думаю, что это имеет какое-либо отношение к замыканию, так как AFAIK имеет дело с включением переменных, а не спецификаторов try-catch-finally?
await
прежде чем вернуть его. Предыдущее решение имело ошибку, которая высвобождала соединение обратно в пул до завершения запроса. Теперь, когда есть выражение await
, оно сначала будет ждать завершения запроса, прежде чем выполнить ключ finally
-block (и вернуть значение). Имеет ли это смысл?