简体   繁体   English

Promise中的Node.js MySQL错误处理

[英]Node.js mysql error handling in promise

I'm using node.js and express, also mysql. 我正在使用node.js并表达,也是mysql。 I use a connection pool to request connections and create a promise on it, to limit callback nightmare, the following snippet is set in a file that I import later, note that that I set an handler on error to not terminate the application in case of anything going really wrong 我使用连接池来请求连接并在其上创建承诺,以限制回调的噩梦,在我稍后导入的文件中设置了以下代码段,请注意,我设置了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);
        });
    });
};

And here is an example of usecase (the idea is to get the connection, chain the query in the then , and if a non fatal error happen I will throw it and handle the connection release in the catch handler 这是一个用例示例(想法是获取连接,在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));
};

The query will fail, but I see that the handler is not even called (I put some trace in it...) and the application terminates on 该查询将失败,但是我发现甚至没有调用该处理程序(我在其中添加了一些跟踪信息...),并且该应用程序终止于

node_modules/mysql/lib/protocol/Parser.js:80
        throw err; // Rethrow non-MySQL errors

Correct querie yoeld no troubles...Any ideas what I did wrong on the error handling ? 正确的查询不会造成麻烦...任何想法我在错误处理上做错了什么?

You're re-throwing the error passed to the callback of your query, which the library you're using then re-throws as well, and finally isn't properly caught and handled anywhere and results in a failure. 您将重新传递传递给查询回调的错误,您正在使用的库也将重新引发该错误,最后在任何地方都无法正确捕获和处理该错误,从而导致失败。 You're not in the context of the Promise when you throw , but the context of the callback function called from the mysql module. throw ,您不在Promise的上下文中,而是从mysql模块调用的回调函数的上下文。

You're also unnecessarily mixing promises and callbacks, in particular the function you're exporting. 您也不必要混合使用Promise和回调,特别是要导出的功能。 Your question indicates that you want to move away from callbacks, so I'm going to base this answer on that indication. 您的问题表明您想摆脱回调,因此我将以该指示为基础。

To solve the main issue, don't throw the error. 要解决主要问题,请不要抛出错误。 Instead, pass it up to the callee: 而是将其传递给被调用者:

const promisify = require("util").promisify;

exports.someRequest = function (ID) {
  return sqlPool.getConnection().then(connection => {
    return promisify(connection.query)("select * from tableNotExist")
      .finally(connection.release);
  });
};

The connection will always be released back to the pool, whether successful or on error. 无论成功还是错误,连接将始终释放回池中。 You can then call the method with: 然后可以使用以下方法调用该方法:

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.
});

If you have the possibility to use async/await , the code can be rewritten: 如果可以使用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();
  }
};

I also recommend using node-mysql2 since they have a Promise-based API in addition to their callback-style API and in my experience better performance as well. 我还建议使用node-mysql2因为它们除了回调样式的API之外,还具有基于Promise的API,并且根据我的经验,它们的性能也更好。 Then you don't have to write these tedious wrappers and instead just require('mysql2/promise') and be good to go. 然后,您不必编写这些繁琐的包装程序,而只require('mysql2/promise')就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM