簡體   English   中英

Promise中的Node.js MySQL錯誤處理

[英]Node.js mysql error handling in promise

我正在使用node.js並表達,也是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);
        });
    });
};

這是一個用例示例(想法是獲取連接,在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

正確的查詢不會造成麻煩...任何想法我在錯誤處理上做錯了什么?

您將重新傳遞傳遞給查詢回調的錯誤,您正在使用的庫也將重新引發該錯誤,最后在任何地方都無法正確捕獲和處理該錯誤,從而導致失敗。 throw ,您不在Promise的上下文中,而是從mysql模塊調用的回調函數的上下文。

您也不必要混合使用Promise和回調,特別是要導出的功能。 您的問題表明您想擺脫回調,因此我將以該指示為基礎。

要解決主要問題,請不要拋出錯誤。 而是將其傳遞給被調用者:

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')就可以了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM