英文:
pg: typescript error after retrieving a client from the connection pool
问题
import pg, { PoolConfig } from 'pg';
const { Pool } = pg;
const pool = new Pool({
user: process.env.USER_NAME,
host: process.env.HOST_NAME,
database: process.env.DATABASE,
password: process.env.PASSWORD,
port: process.env.DB_PORT
} as PoolConfig);
export {
pool
};
// The code you provided appears to be in TypeScript and JavaScript. If you have any specific questions or need assistance with this code, please let me know.
英文:
import pg, {PoolConfig} from 'pg';
const { Pool } = pg;
const pool = new Pool({
user: process.env.USER_NAME,
host: process.env.HOST_NAME,
database: process.env.DATABASE,
password: process.env.PASSWORD,
port: process.env.DB_PORT
} as PoolConfig);
export {
pool
};
I am trying to retrieve a client from the postgresql connection pool and am receiving a type error when I call "client.query". I am receiving the following error for the ".query" function, "TS2339: Property 'query' does not exist on type 'void'". This is a typescript node.js application.
const client = await pool.connect();
try {
const res = await client.query('SELECT …’, [….]);
if (!res?.rows[0])
return null;
return res.rows[0];
} catch (e) {
throw e;
} finally {
client.release();
}
This is my tsconfig.json file:
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"strict": true,
"sourceMap": true,
"outDir": "build",
"moduleResolution": "node",
"resolveJsonModule": true,
"lib": ["es2017"],
"allowSyntheticDefaultImports": true,
"skipLibCheck": true
},
"files": [
"./node_modules/@types/node/index.d.ts"
],
"exclude": [
"node_modules",
"build"
],
"include": [
"**/*.ts"
]
}
I also added the package @types/pg and am not sure what could be missing.
答案1
得分: 1
以下是翻译好的部分:
假设你展示的内容并非导致错误的代码的精确复制:如果尝试混合使用 connect() 调用,我会预期出现以下情况:
-
在某处复制
connect()调用,导致pool.connect()返回一个客户端,然后再次调用connect(),这会返回一个void。 -
在从池中获取连接时尝试运行一个查询,通过将回调函数作为参数传递给
connect():然后尝试使用该
connect()结果作为pg.Client来运行另一个查询,尽管在这种情况下,如消息所示并由 qrsngky 指出,它是void。pool.connect()承诺仅在没有任何参数的情况下调用时返回客户端。pool.connect() => Promise<pg.Client>这种情况下可能的一种用例是某种连接设置脚本 - 您可以处理
.on()连接或获取事件。 -
在从配置和初始化池的模块中导出时,暴露一个修改/重载的
connect(),使看似无参数的调用默认使用可调用的形式或复制调用。所以以上任一情况,只是在其他地方隐藏起来。
还有一些双重检查可能会有所帮助:你确定导出的 pool 与后来调用 connect() 的是相同的吗?pg 包是否是你期望的,版本是否正确?
作为一种解决方法,不管导致这个问题的是什么:如果你的查询中没有定义事务,可以尝试直接使用 pool.query():
const res = await pool.query('SELECT …', [….]);
if (!res?.rows[0])
return null;
return res.rows[0];
无需通过 connect() 先从池中获取客户端,然后稍后使用 finally {client.release();},因为 pool.query() 会自动处理这两个操作。由于 catch 只重新抛出错误,finally 只释放连接,因此可以删除整个 try 块。这实际上是包作者推荐的做法:
我发现
pool.query在许多情况下都很方便,除非我需要一个事务。
英文:
Assuming what you're showing is not an exact 1:1 copy of the code that actually caused the error: I would expect this to happen if you attempted to mix your connect() calls by:
-
duplicating the
connect()call somewhere, leading topool.connect()returning a client, which you again callconnect()on, which promises avoid. -
trying to run one query when acquiring the connection from the pool, by giving
connect()a callback function as argument:
>pool.connect(callback: (...) => void) => voidthen trying to use that
connect()result as apg.Clientto run another query, even though in this scenario it'svoidas indicated by the message and pointed out by qrsngky.pool.connect()promises to bring back a client only when called without any arguments.
>pool.connect() => Promise<pg.Client>One use case that comes to mind for this would be some kind of connection setup script - you could handle it
.on()connect or acquire events. -
exposing an altered/overloaded
connect()when exporting from the module where you've configured and initialised the pool, making a seemingly no-arg call default to the form using a callable or duplicating the call. So either of the above, just elsewhere, hidden away.
A few double checks could be helpful, too: are you sure the pool you exported is the same thing you're calling connect() on later? Is pg package the one you expect, the version you expect?
As a workaround, regardless of what caused this: if you're not defining transactions inside your query, you could try to use pool.query() directly:
const res = await pool.query('SELECT …', [….]);
if (!res?.rows[0])
return null;
return res.rows[0];
No need to acquire the client from the pool through connect() first, then finally {client.release();} later because pool.query() handles both automatically. Since the catch only re-throws the error and finally only releases the connection, the entire try block could be removed. That's actually what the package author recommends:
>I find pool.query to be a handy shortcut many situations and use it exclusively unless I need a transaction.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论