我是 Node-JS 的新手,正在尝试掌握异步概念和承诺。 我正在尝试确保在呈现网络服务器时数据库数据的可用性。
使用代码,我似乎已经实现了正确的时间——当数据可用时,函数 buildhtml 被调用。经过一夜的研究,第一次成功。
现在我正试图找到将数据传递到网络服务器/快递的正确方法。
我要找的数据现在封装在一个promise-object中,无法处理。我看过许多其他帖子,但无法为您的示例得出解决方案。
问题:以消费方式(基本上是promise对象,但没有外层promise封装)移交数据的最佳实践方案是什么?我的想法是完全错误的还是我错过了一小步?
非常感谢任何答案,并提前致谢!
//DB Load Users
const promise = new Promise((resolve, reject) => {
db.connect(function(err) {
if (err) throw err;
console.log("Connected!");
var sql = "SELECT username, useremail, userage, useruniqueid FROM users";
db.query(sql, function(err, result) {
if (err) throw err;
const jsonresult = JSON.parse(JSON.stringify(result)); //to clear RowDatePacket
resolve(jsonresult);
});
})
})
promise
.then(buildhtml)
//Render (express) HTML with promise resolve after DB-query
function buildhtml() {
app.get("/", function(req, res) {
res.render("home", {
data: promise
})
})
}
这是 console.log(promise) 在 buildhtml() 中的输出:
Connected!
Promise {
[
{
username: 'admin',
useremail: '888883895',
userage: '33',
useruniqueid: 1
},
{
username: 'admin',
useremail: '888883895',
userage: '22',
useruniqueid: 2
},
{
username: 'admin',
useremail: '888883895',
userage: '22',
useruniqueid: 3
},
{
username: 'admin',
useremail: '888883895',
userage: '22',
useruniqueid: 4
},
{
username: 'pushy boi',
useremail: '[email protected]',
userage: '65',
useruniqueid: 5
},
{
username: 'push attempt',
useremail: '[email protected]',
userage: '65',
useruniqueid: 6
},
{
username: 'instead of push db',
useremail: '[email protected]',
userage: '37',
useruniqueid: 104
},
{
username: '111',
useremail: '111',
userage: '11',
useruniqueid: 111
},
{
username: null,
useremail: null,
userage: null,
useruniqueid: 112
},
{
username: 'Max Mustermann',
useremail: '[email protected]',
userage: '44',
useruniqueid: 333
}
]
}
这就是你应该如何重写它。首先,将获取 MySQL 数据的代码包装在一个函数中。
function getUsers() {
return new Promise((resolve, reject) => {
db.connect(function(err) {
if (err) reject(err);
console.log("Connected!");
var sql = "SELECT username, useremail, userage, useruniqueid FROM users";
db.query(sql, function(err, result) {
if (err) reject(err);
resolve(result[0]);
});
})
})
}
请注意,我将您的
throw
s 更改为 reject
并删除了不需要的 JSON 步骤。
如果你使用像
mysql2/promises
这样的基于承诺的 mysql 库并使用连接池,那就更好了:
async function getUsers() {
const result = await pool.query("SELECT username, useremail, userage, useruniqueid FROM users");
return result[0];
}
相比之下好干净!
然后定义路线并在需要时调用
getUsers
:
app.get("/", function(req, res) {
getUsers()
.then(result => {
res.render("home", {
data: result
})
})
.catch(err => {
res.status(500);
console.error(err);
});
});
你有什么should工作但是引入了潜在的竞争条件......如果在承诺解决之前向
GET /
提出请求怎么办? Express 只会返回 404,因为它不知道路线。
不是在承诺解决后注册你的路由处理程序,而是在路由处理程序中解决承诺
app.get("/", async (_req, res, next) => {
try {
res.render("home", { data: await promise });
} catch (err) {
next(err);
}
});
请注意,您的查询只会在您的 Express 服务器启动时执行一次。这可能是也可能不是您想要的。比较典型的做法是每次请求时执行查询。