我使用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请求时,它返回promisePromise { <pending> }
,而不是我期望的json对象数组。有一个控制器:
exports.getUsers = function (req, res) {
let users = userModel.getAllUsers();
console.log(users); // here it outputs Promise { <pending> }
res.json(users);
};
如何获取数组而不是promise?
让我们分解一下您的代码。您正在导出设计中的一个函数getUsers
,该函数应该返回一系列用户对象。但它没有——db.any(...)
返回一个Promise
。你认为你还能对返回的对象调用then
吗?then
是Promise
类的一个成员函数,您将另一个函数传递给then
以处理实际数据(作为参数传递给传递给then
的函数(。这意味着data
,传递给在db.any(...)
调用的返回值上调用的then
调用,实际上就是您所追求的用户序列。
您所犯的错误是假设,如果您从传递给then
的回调中return data
,它将成为then(...)
调用的返回值。它不会。then
总是返回一个Promise
——无论您从回调到then
返回什么,都将成为返回的promise的解析值,但返回的是promise,这就是为什么users
变量是Promise
。
您需要阅读更多关于promise的信息,以及如何异步(在运行脚本之间(解析它们,以及如何在解析它们时同步代码。
提示:使用await
关键字等待并使用给定promise的值,例如从传递给then(...)
调用的回调中返回的值,或接受返回promise的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
关键字后表达的promise解析为值时恢复,该值将分配给users
变量。
使用async
和await
确实需要一个可以支持它们的Node.js版本,但当前版本需要(截至撰写本文时(。
否则,你仍然可以保留getUsers
函数,但你需要以不同的方式使用它,因为你不能使用await
——必须像引入await
和async
之前那样使用promise,比如:
getUsers().then(users => {
/// Do something with the `users` array.
});
无论如何,你对promise如何工作的理解似乎有一些漏洞,我建议你这次通过阅读这些漏洞来填补这些漏洞,而不仅仅是直接进入pg-promise
API,它建立在这些漏洞的基础上。
就像您已经发现的那样,userModel.getAllUsers()
将返回一个promise而不是一个数组。你需要等待这个承诺得到解决。这可以使用async function
来完成。
exports.getUsers = async function (req, res) {
let users = await userModel.getAllUsers();
console.log(users);
res.json(users);
};
请注意,
async function
将始终返回一个promise。
或者您可以使用返回promise的then
方法。
exports.getUsers = function (req, res) {
userModel.getAllUsers().then(users => {
console.log(users);
res.json(users);
});
};