我应该在哪里初始化 pg-promise
Where should I initialize pg-promise
刚开始学习nodejs-postgres
,发现了pg-promise
包。
我阅读了文档和示例,但我不明白应该将初始化代码放在哪里?我使用 Express,我有很多路线。
我必须将整个初始化(包括 pg-monitor
init)放在我想查询数据库的每个文件中,或者我需要包含并且 initalize/configure
它们仅在 server.js?
如果我只在 server.js 中初始化它们,我应该在需要数据库查询的地方包含什么其他文件?
也就是说。我不清楚 pg-promise 和 pg-monitor configuration/initalization
是全局操作还是本地操作?
还不清楚我是否需要为每个查询创建一个 db 变量并结束 pgp?
var db = pgp(connection);
db.query(...).then(...).catch(...).finally(**pgp.end**);
您只需初始化一次数据库连接。如果要在模块之间共享,那就放到自己的模块文件中,像这样:
const initOptions = {
// initialization options;
};
const pgp = require('pg-promise')(initOptions);
const cn = 'postgres://username:password@host:port/database';
const db = pgp(cn);
module.exports = {
pgp, db
};
UPDATE-1
如果您尝试创建多个具有相同连接详细信息的数据库对象,该库将向控制台输出一条警告:
WARNING: Creating a duplicate database object for the same connection.
at Object.<anonymous> (D:\NodeJS\tests\test2.js:14:6)
这表明您的数据库使用模式不正确,即您应该共享数据库对象,如上所示,而不是重新创建它。自版本 6.x 以来,它变得至关重要,每个数据库对象都维护自己的连接池,因此复制这些连接池还会导致连接使用率低下。
此外,没有必要导出 pgp
- 已初始化的库实例。相反,您可以这样做:
module.exports = db;
如果在某些模块中您需要使用库的根目录,您可以通过 属性 $config:
访问它
const db = require('../db'); // your db module
const pgp = db.$config.pgp; // the library's root after initialization
UPDATE-2
一些开发人员报告 (issue #175) 某些框架,如 NextJS 设法以打破单例模式的方式加载模块,这导致数据库模块加载不止一次,并产生duplicate database
警告,即使从 NodeJS 的角度来看它应该可以正常工作。
下面是此类集成问题的变通方法,方法是使用 Symbol 强制单例进入全局范围。让我们创建一个可重用的帮助程序来创建单例...
// generic singleton creator:
export function createSingleton<T>(name: string, create: () => T): T {
const s = Symbol.for(name);
let scope = (global as any)[s];
if (!scope) {
scope = {...create()};
(global as any)[s] = scope;
}
return scope;
}
使用上面的帮助程序,您可以将您的 TypeScript 数据库文件修改为:
import * as pgLib from 'pg-promise';
const pgp = pgLib(/* initialization options */);
interface IDatabaseScope {
db: pgLib.IDatabase<any>;
pgp: pgLib.IMain;
}
export function getDB(): IDatabaseScope {
return createSingleton<IDatabaseScope>('my-app-db-space', () => {
return {
db: pgp('my-connect-string'),
pgp
};
});
}
然后,在任何使用数据库的文件的开头,您可以这样做:
import {getDB} from './db';
const {db, pgp} = getDB();
这将确保持久的单例模式。
pgp 中的"connection" 实际上是一个自动管理的多连接池。每次发出请求时,都会从池中抓取一个连接,打开,使用,然后关闭并返回到池中。这就是为什么 vitaly-t 如此重视只为整个应用程序创建一个 pgp 实例的重要原因。结束连接的唯一原因是,如果您确定已使用完数据库,即您正在优雅地关闭您的应用程序。
刚开始学习nodejs-postgres
,发现了pg-promise
包。
我阅读了文档和示例,但我不明白应该将初始化代码放在哪里?我使用 Express,我有很多路线。
我必须将整个初始化(包括 pg-monitor
init)放在我想查询数据库的每个文件中,或者我需要包含并且 initalize/configure
它们仅在 server.js?
如果我只在 server.js 中初始化它们,我应该在需要数据库查询的地方包含什么其他文件?
也就是说。我不清楚 pg-promise 和 pg-monitor configuration/initalization
是全局操作还是本地操作?
还不清楚我是否需要为每个查询创建一个 db 变量并结束 pgp?
var db = pgp(connection);
db.query(...).then(...).catch(...).finally(**pgp.end**);
您只需初始化一次数据库连接。如果要在模块之间共享,那就放到自己的模块文件中,像这样:
const initOptions = {
// initialization options;
};
const pgp = require('pg-promise')(initOptions);
const cn = 'postgres://username:password@host:port/database';
const db = pgp(cn);
module.exports = {
pgp, db
};
UPDATE-1
如果您尝试创建多个具有相同连接详细信息的数据库对象,该库将向控制台输出一条警告:
WARNING: Creating a duplicate database object for the same connection.
at Object.<anonymous> (D:\NodeJS\tests\test2.js:14:6)
这表明您的数据库使用模式不正确,即您应该共享数据库对象,如上所示,而不是重新创建它。自版本 6.x 以来,它变得至关重要,每个数据库对象都维护自己的连接池,因此复制这些连接池还会导致连接使用率低下。
此外,没有必要导出 pgp
- 已初始化的库实例。相反,您可以这样做:
module.exports = db;
如果在某些模块中您需要使用库的根目录,您可以通过 属性 $config:
访问它const db = require('../db'); // your db module
const pgp = db.$config.pgp; // the library's root after initialization
UPDATE-2
一些开发人员报告 (issue #175) 某些框架,如 NextJS 设法以打破单例模式的方式加载模块,这导致数据库模块加载不止一次,并产生duplicate database
警告,即使从 NodeJS 的角度来看它应该可以正常工作。
下面是此类集成问题的变通方法,方法是使用 Symbol 强制单例进入全局范围。让我们创建一个可重用的帮助程序来创建单例...
// generic singleton creator:
export function createSingleton<T>(name: string, create: () => T): T {
const s = Symbol.for(name);
let scope = (global as any)[s];
if (!scope) {
scope = {...create()};
(global as any)[s] = scope;
}
return scope;
}
使用上面的帮助程序,您可以将您的 TypeScript 数据库文件修改为:
import * as pgLib from 'pg-promise';
const pgp = pgLib(/* initialization options */);
interface IDatabaseScope {
db: pgLib.IDatabase<any>;
pgp: pgLib.IMain;
}
export function getDB(): IDatabaseScope {
return createSingleton<IDatabaseScope>('my-app-db-space', () => {
return {
db: pgp('my-connect-string'),
pgp
};
});
}
然后,在任何使用数据库的文件的开头,您可以这样做:
import {getDB} from './db';
const {db, pgp} = getDB();
这将确保持久的单例模式。
pgp 中的"connection" 实际上是一个自动管理的多连接池。每次发出请求时,都会从池中抓取一个连接,打开,使用,然后关闭并返回到池中。这就是为什么 vitaly-t 如此重视只为整个应用程序创建一个 pgp 实例的重要原因。结束连接的唯一原因是,如果您确定已使用完数据库,即您正在优雅地关闭您的应用程序。