英文:
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) => void
then trying to use that
connect()
result as apg.Client
to run another query, even though in this scenario it'svoid
as 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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论