处理 Knex pg 数据库错误的正确方法是什么

AZZ*_*Z_B 5 javascript postgresql error-handling knex.js

我使用 postgres 和 knex javascript 库来构建我的 sql 查询。我想处理来自 postgres 服务器的所有抛出的错误,因此我想要执行此操作的方法是检查抛出的错误的类型。

try {
   // knex query here
} catch(error) {
    if(error instanceof DatabaseError) {
      // handle pg error by checking error.code or something else
      // then send an custom error message to the client
    }

    // handle another error here which is not caused by the postgres server
}
Run Code Online (Sandbox Code Playgroud)

有什么办法可以处理这样的错误吗?

mac*_*ost 5

捕获 Knex/DB 错误:

您可以使用async/await语法:

async function() {
    try {
       await knex(/* knex query here*/)
    } catch(error) {
        if(error instanceof DatabaseError) {
          // handle pg error by checking error.code or something else
          // then send an custom error message to the client
        }
        // handle another error here which is not caused by the postgres server
    }
Run Code Online (Sandbox Code Playgroud)

如果由于某种原因您不想使用该(较新的)语法,您还可以链接.catch...

knex(/* knex query here*/)
    .then(doWhatever)
    .catch(error => {
         if(error instanceof DatabaseError) { // ...
    });
Run Code Online (Sandbox Code Playgroud)

或者,您也可以使用 Knex 的查询错误(https://knexjs.org/#Interfaces-query-error)...但就我个人而言,我从未见过内置 Promise 处理程序工作正常的情况。

(编辑)区分 PG 错误和 Knex 错误:

如果你想区分 Knex 和 PG 特定的错误,你可以直接将错误处理程序连接到 PG 连接(绕过 Knex),如下所示:

function afterCreate(connection, callback) {
  connection.on("error", connectionError);
  callback(null, connection);
}

db.client.pool.config.afterCreate = afterCreate;
Run Code Online (Sandbox Code Playgroud)

如果你这样做,你将不需要error instanceof DatabaseError,因为 捕获的所有错误都connection.on 是 PG 错误。

您可能还会发现这个问题线程(我从中获取代码的地方)很有用: https: //github.com/knex/knex/issues/522,因为它讨论了 Knex 中的错误处理,特别是底层数据库的处理错误。

(编辑)但是当我发现错误时如何区分错误?

不幸的是,我不认为 PG 错误没有独特的原型(即类)或其他显着特征。您可以通过查看示例(来自我链接的该线程)来看到这一点:

{"code":"ECONNREFUSED","errno":"ECONNREFUSED","syscall":"connect","address":"127.0.0.1","port":5432}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,没有办法查看并知道“这是来自 PostgreSQL”,除非您开始检查特定功能,例如(错误上code === 'ECONNREFUSED'没有标志)。isPg: true

为什么 Knex 不智能地为我们识别数据库错误呢?来自同一问题线程:

创建像 redis 为 knex 那样的事件几乎是不可能的,因为有许多不同的数据库驱动程序实际上不支持侦听连接错误

-elhigu(Knex 团队成员)