启动应用程序时使用pg-promise验证数据库连接

时间:2021-10-11 15:36:40

I am building an express application that connects to a postgres database using the pg-promise module.

我正在构建一个使用pg-promise模块连接到postgres数据库的快速应用程序。

I would like to ensure that the database connection is successful when starting the application server. In other words, if the connection to the database fails, I'd like to throw an error.

我想确保启动应用程序服务器时数据库连接成功。换句话说,如果与数据库的连接失败,我想抛出一个错误。

My server.js file is as follows:

我的server.js文件如下:

const express = require("express");

const databaseConfig= {
  "host": "localhost",
  "port": 5432,
  "database": "library_app",
  "user": "postgres"
};

const pgp = require("pg-promise")({});
const db = pgp(databaseConfig);

const app = express();
const port = 5000;

app.listen(port, (err) => {
  console.log(`running server on port: ${port}`);
});

The current configuration will start the express server regardless of whether the database connection is valid, which is not the behavior I would like.

无论数据库连接是否有效,当前配置都将启动快速服务器,这不是我想要的行为。

I tried browsing the docs but couldn't find a solution. I also tried const db = pgp(databaseConfig).catch((err) => { // blow up });, but that didn't work because pgp does not return a promise.

我尝试浏览文档但找不到解决方案。我也尝试了const db = pgp(databaseConfig).catch((err)=> {// blow up});,但是这没有用,因为pgp没有返回一个promise。

1 个解决方案

#1


33  

I am the author of pg-promise ;) And this isn't the first time this question is asked, so I'm giving it a detailed explanation here.

我是pg-promise的作者;)这不是第一次提出这个问题,所以我在这里给出一个详细的解释。

When you instantiate a new database object like this:

当您实例化一个新的数据库对象时,如下所示:

const db = pgp(connection);

...all it does - creates the object, but it does not try to connect. The library is built on top of the connection pool, and only the actual query methods request a connection from the pool.

...所有它 - 创建对象,但它不会尝试连接。该库建立在连接池之上,只有实际的查询方法才能从池中请求连接。

From the official documentation:

从官方文档:

Object db represents the database protocol, with lazy database connection, i.e. only the actual query methods acquire and release the connection. Therefore, you should create only one global/shared db object per connection details.

对象db表示具有惰性数据库连接的数据库协议,即只有实际的查询方法获取并释放连接。因此,您应该为每个连接详细信息仅创建一个全局/共享数据库对象。

However, you can ask the library to connect without executing any query, by using method connect, as shown further.

但是,您可以通过使用方法connect来请求库连接而不执行任何查询,如进一步所示。

And while this method is no longer a recommended way for chaining queries, ever since support for Tasks has been introduced (as a safer approach), it still comes in handy checking for the connection in general.

虽然这种方法不再是链接查询的推荐方法,但自从引入对Task的支持以来(作为一种更安全的方法),它仍然可以方便地检查连接。

I copied the example from my own post: https://github.com/vitaly-t/pg-promise/issues/81

我从我自己的帖子中复制了这个例子:https://github.com/vitaly-t/pg-promise/issues/81

Below is an example of doing it in two ways at the same time, so you can choose whichever approach you like better.

下面是一个同时以两种方式进行操作的示例,因此您可以选择您更喜欢的方法。

const initOptions = {
    // global event notification;
    error(error, e) {
        if (e.cn) {
            // A connection-related error;
            //
            // Connections are reported back with the password hashed,
            // for safe errors logging, without exposing passwords.
            console.log('CN:', e.cn);
            console.log('EVENT:', error.message || error);
        }
    }
};

const pgp = require('pg-promise')(initOptions);

// using an invalid connection string:
const db = pgp('postgresql://userName:password@host:port/database');

db.connect()
    .then(obj => {
        obj.done(); // success, release the connection;
    })
    .catch(error => {
        console.log('ERROR:', error.message || error);
    });

Outputs:

输出:

CN: postgresql://userName:########@host:port/database EVENT: getaddrinfo ENOTFOUND host host:5432 ERROR: getaddrinfo ENOTFOUND host host:5432

CN:postgresql:// userName:######## @ host:port / database EVENT:getaddrinfo ENOTFOUND主机主机:5432 ERROR:getaddrinfo ENOTFOUND主机主机:5432

Every error in the library is first reported through the global error event handler, and only then the error is reported within the corresponding .catch handler.

首先通过全局错误事件处理程序报告库中的每个错误,然后在相应的.catch处理程序中报告错误。

Alternative

Instead of establishing the connection manually, you can simply execute a type of query that would always succeed for a valid connection, like the following one:

您可以简单地执行一种始终成功进行有效连接的查询,而不是手动建立连接,如下所示:

db.proc('version')
    .then(data => {
        // SUCCESS
        // data.version =
        // 'PostgreSQL 9.5.1, compiled by Visual C++ build 1800, 64-bit'
    })
    .catch(error => {
        // connection-related error
    });

API links:

API链接:

#1


33  

I am the author of pg-promise ;) And this isn't the first time this question is asked, so I'm giving it a detailed explanation here.

我是pg-promise的作者;)这不是第一次提出这个问题,所以我在这里给出一个详细的解释。

When you instantiate a new database object like this:

当您实例化一个新的数据库对象时,如下所示:

const db = pgp(connection);

...all it does - creates the object, but it does not try to connect. The library is built on top of the connection pool, and only the actual query methods request a connection from the pool.

...所有它 - 创建对象,但它不会尝试连接。该库建立在连接池之上,只有实际的查询方法才能从池中请求连接。

From the official documentation:

从官方文档:

Object db represents the database protocol, with lazy database connection, i.e. only the actual query methods acquire and release the connection. Therefore, you should create only one global/shared db object per connection details.

对象db表示具有惰性数据库连接的数据库协议,即只有实际的查询方法获取并释放连接。因此,您应该为每个连接详细信息仅创建一个全局/共享数据库对象。

However, you can ask the library to connect without executing any query, by using method connect, as shown further.

但是,您可以通过使用方法connect来请求库连接而不执行任何查询,如进一步所示。

And while this method is no longer a recommended way for chaining queries, ever since support for Tasks has been introduced (as a safer approach), it still comes in handy checking for the connection in general.

虽然这种方法不再是链接查询的推荐方法,但自从引入对Task的支持以来(作为一种更安全的方法),它仍然可以方便地检查连接。

I copied the example from my own post: https://github.com/vitaly-t/pg-promise/issues/81

我从我自己的帖子中复制了这个例子:https://github.com/vitaly-t/pg-promise/issues/81

Below is an example of doing it in two ways at the same time, so you can choose whichever approach you like better.

下面是一个同时以两种方式进行操作的示例,因此您可以选择您更喜欢的方法。

const initOptions = {
    // global event notification;
    error(error, e) {
        if (e.cn) {
            // A connection-related error;
            //
            // Connections are reported back with the password hashed,
            // for safe errors logging, without exposing passwords.
            console.log('CN:', e.cn);
            console.log('EVENT:', error.message || error);
        }
    }
};

const pgp = require('pg-promise')(initOptions);

// using an invalid connection string:
const db = pgp('postgresql://userName:password@host:port/database');

db.connect()
    .then(obj => {
        obj.done(); // success, release the connection;
    })
    .catch(error => {
        console.log('ERROR:', error.message || error);
    });

Outputs:

输出:

CN: postgresql://userName:########@host:port/database EVENT: getaddrinfo ENOTFOUND host host:5432 ERROR: getaddrinfo ENOTFOUND host host:5432

CN:postgresql:// userName:######## @ host:port / database EVENT:getaddrinfo ENOTFOUND主机主机:5432 ERROR:getaddrinfo ENOTFOUND主机主机:5432

Every error in the library is first reported through the global error event handler, and only then the error is reported within the corresponding .catch handler.

首先通过全局错误事件处理程序报告库中的每个错误,然后在相应的.catch处理程序中报告错误。

Alternative

Instead of establishing the connection manually, you can simply execute a type of query that would always succeed for a valid connection, like the following one:

您可以简单地执行一种始终成功进行有效连接的查询,而不是手动建立连接,如下所示:

db.proc('version')
    .then(data => {
        // SUCCESS
        // data.version =
        // 'PostgreSQL 9.5.1, compiled by Visual C++ build 1800, 64-bit'
    })
    .catch(error => {
        // connection-related error
    });

API links:

API链接: