您只需要初始化一次数据库连接。如果要在模块之间共享,则将其放入自己的模块文件中,如下所示:
const initOptions = {
};
const pgp = require('pg-promise')(initOptions);
const cn = 'postgres://username:password@host:port/database';
const db = pgp(cn);
module.exports = {
pgp, db
};
请查看支持的初始化选项。
更新-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
更新-2
一些开发人员报告(问题#175)称,某些框架(如NextJS)以破坏单例模式的方式加载模块,这导致数据库模块被加载超过一次,并产生“重复数据库”警告,尽管从NodeJS的角度来看它应该可以正常工作。
以下是针对此类集成问题的解决方法,通过使用Symbol将单例强制到全局范围中。让我们创建一个可重用的辅助工具来创建单例......
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();
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();
这将确保单例模式的持久性。