如何从 pg-promise 中的 db.any() 承诺中获取价值?

Posted

技术标签:

【中文标题】如何从 pg-promise 中的 db.any() 承诺中获取价值?【英文标题】:How to get value from db.any() promise in pg-promise? 【发布时间】:2020-11-02 21:32:55 【问题描述】:

我使用 pg-promise 并尝试在用户模型中向数据库发出请求以获取所有用户的数组,如下所示:

 exports.getAllUsers = function () 
      let users = db.any("SELECT * FROM users;").then(function (data) 
        return data; // in debug mode data is my expected array 
      );
      return users;
    ;

但是当我从控制器发出 get 请求时,它返回 promise Promise <pending> ,而不是我预期的 json 对象数组。 有一个控制器:

exports.getUsers = function (req, res) 
   let users = userModel.getAllUsers();
   console.log(users); // here it outputs Promise  <pending> 
   res.json(users);
 ;

如何获取数组而不是promise?

【问题讨论】:

您正在返回 then 函数调用的返回值。你认为这个电话会返回什么?它返回一个Promise 对象。 @amn 好的,知道了。但是如何获得我想要的价值?在调试模式下,“数据”是一个数组。 data 作为数组与调试模式无关,我向你保证——传递给then 的回调总是使用已解决的承诺的值调用你打电话给then。如果db.any 返回的promise 用一个数组解析,那么data 就是那个数组,句号。如果您想向我保证这是调试模式,则必须有其他东西在起作用。当然,解析值的类型可能会有所不同——但这将是 pg-promise 的内部工作原理。 【参考方案1】:

让我们分解您的代码。您正在导出设计的函数getUsers,它应该返回一系列用户对象。但它没有——db.any(...) 返回一个Promise。你认为你还能如何在返回的对象上调用thenthen is a member function of the Promise class,然后将另一个函数传递给 then 以处理实际数据(作为参数传递给传递给 then 的函数)。这意味着确实 data 传递给在 db.any(...) 调用的返回值上调用的 then 调用,是您所追求的用户序列。

您犯的错误是假设如果您将return data 从回调传递给then,它将成为then(...) 调用的返回值。它不会then always 返回一个 Promise —— 无论你从回调中返回到 then 的什么,都将成为返回的承诺的解析值,但它是返回的承诺,这就是为什么您的 users 变量是 Promise

您需要阅读更多关于 Promise 的信息,以及它们是如何异步解析的(在运行脚本之间),以及如何在它们解析时同步您的代码。 p>

提示:使用 await 关键字等待并使用给定承诺的值,例如从传递给 then(...) 调用的回调中返回的值,接受设计您的 getUsers 函数返回一个承诺并调整其余代码以使用它,而不使用 await

您的getAllUsers 函数可以简化为:

exports.getAllUsers = function () 
    return db.any("SELECT * FROM users;");

...然后使用await,您可以像这样使用它:

let users = await getUsers();

上述语句必须是标记为 async 的函数的一部分,但 ECMAScript 需要明确标记这些以允许使用 await 表达式:

async function whatever() 
    let users = await getUsers();
    /// ...

调用 async 函数的脚本(例如包含上述语句的脚本)的执行将在每个 await 表达式处被 javascript 解释器中断,并在 await 关键字后表达的承诺解析时恢复到一个值,该值被分配给users 变量。

使用 asyncawait 确实需要可以支持它们的 Node.js 版本,但当前版本需要(截至撰写本文时)。

否则你仍然可以保留getUsers 函数,但是你需要以不同的方式使用它,因为你不能使用await——必须像在引入awaitasync 之前那样使用promise ,比如:

getUsers().then(users => 
    /// Do something with the `users` array.
);

无论如何,您对 Promise 的工作原理的理解似乎存在一些漏洞,我建议您这次通过阅读它们来填补这些漏洞,而不仅仅是直接使用构建的 pg-promise API在他们身上。

【讨论】:

一般来说,return await 是一种反模式。 我会详细说明以进一步减少功能,消除反模式。【参考方案2】:

就像你已经发现userModel.getAllUsers() 将返回一个承诺而不是一个数组。你需要等待这个承诺得到解决。这可以使用async function 来完成。

exports.getUsers = async function (req, res) 
   let users = await userModel.getAllUsers();
   console.log(users);
   res.json(users);
;

请注意,async function 将始终返回一个承诺。

或者你可以使用返回的promise的then方法。

exports.getUsers = function (req, res) 
   userModel.getAllUsers().then(users => 
     console.log(users);
     res.json(users);
   );
;

【讨论】:

以上是关于如何从 pg-promise 中的 db.any() 承诺中获取价值?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用pg-promise同时从多个查询中获得结果?

pg-promise:在事务中的下一个查询中使用一个查询的结果

如何使用 pg-promise 帮助器返回插入查询结果值

Next.js API 路由与 pg-promise

如何使用nodejs pg-promise库将带有uuid数组的记录插入pg表

Pg-promise插入/事务在异步队列中不起作用