pg: typescript error after retrieving a client from the connection pool

huangapple go评论68阅读模式
英文:

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()

    pool.connect(callback: (...) => void) => void

    然后尝试使用该 connect() 结果作为 pg.Client 来运行另一个查询,尽管在这种情况下,如消息所示并由 qrsngky 指出,它是 voidpool.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 to pool.connect() returning a client, which you again call connect() on, which promises a void.

  • trying to run one query when acquiring the connection from the pool, by giving connect() a callback function as argument:
    >pool.connect(callback: (...) =&gt; void) =&gt; void

    then trying to use that connect() result as a pg.Client to run another query, even though in this scenario it's void 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() =&gt; Promise&lt;pg.Client&gt;

    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(&#39;SELECT …&#39;, [….]);
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.

huangapple
  • 本文由 发表于 2023年2月24日 13:52:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75553040.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定