gpt4 book ai didi

node.js - NodeJS 不那么明显的回调和更多的结构

转载 作者:搜寻专家 更新时间:2023-10-31 23:55:48 24 4
gpt4 key购买 nike

NodeJS 的一个优点是它的异步和非阻塞 I/O,一方面对我来说这很好,但另一方面每天都会让我的脖子断掉。

我认为自己是 NodeJS/Async 新手,我经常会遇到这样的代码:

function(req, res) {
req.assert("name", "Lobbyname is required").notEmpty();
req.assert("name", "Lobbyname length should be between 4 and 64 characters").len(4, 64);
req.assert("game", "Game not found").isInt();

req.sanitize("game").toInt();
var userId = req.user.id;

var errors = req.validationErrors();
var pg_errors = [];
var games = null;
if (errors) {
console.log(errors);
client.query("SELECT * FROM games", function(err, result) {
if (!err) {
games = result.rows;
res.render("lobby/create", {
title: "Create a new lobby",
games: games,
errors: errors.toString()
});
}
else {
res.send("error");
}
});
}
else {
errors = null;
client.query("SELECT COUNT(*) as in_lobbies FROM users u RIGHT JOIN lobby_userlist ul ON ul.user_id = u.id WHERE u.id = $1", [userId], function(err, result) {
if (!err) {
console.log(result.rows[0]);
if (result.rows[0].in_lobbies < 1) {
client.query("SELECT COUNT(*) as hosting_lobbies FROM lobbies WHERE owner = $1", [userId], function(err, result) {
if (!err) {
if (result.rows[0].hosting_lobbies < 1) {
client.query("INSERT INTO lobbies(name, game, owner) VALUES($1, $2, $3)", [req.param("name"), req.param("game"), userId], function(err, result) {
if (!err) {
res.redirect("/lobby");
}
else {
pg_errors.push(err);
console.log(err);
}
});
}
else {
errors = "You can only host one lobby at a time";
}
}
else {
pg_errors.push(err);
client.query("SELECT * FROM games", function(err, result) {
if (!err) {
games = result.rows;

res.render("lobby/create", {
title: "Create a new lobby",
games: games,
errors: errors
});
}
else {
pg_errors.push(err);
}
});
}
});
}
else {
pg_errors.push(err);
}
}
});

console.log("pg_errors");
console.log(pg_errors);
console.log("pg_errors _end");

if (pg_errors.length < 1) {
console.log("no errors");
}
else {
console.log(pg_errors);
res.send("error service operation failed");
}
}
}

这是我使用以下 npm 包编写的示例:

  • pg(母语)
  • express
  • express-validator( Node 验证器的中间件)
  • 护照(授权中间件)

检查用户提供的输入是否有效是最不重要的问题,我在断言变量的位置检查并返回页面的呈现版本,打印出错误给用户。

但是如果我们首先通过验证错误,我们假设“大厅”已准备好插入数据库,然后我想确保用户没有打开其他大厅并且不是另一个大厅的成员。那么现在我最终将一个查询放入另一个查询,理论上我必须将我的 View 渲染函数(res.render())放入每个查询回调中,如果查询遇到错误或返回表明不允许用户的结果创建一个大厅。我不想要那样,而且它似乎不太可行。

我尝试从查询回调中删除渲染逻辑和所有其他逻辑,而是让查询回调设置错误数组或变量来指示成功或失败,在我的查询代码下方我将检查 if(errors) renderPageWithErrors。

由于 nodejs 的异步行为,这会导致奇怪的错误,在这种情况下,res.redirect() 在 res.render() 之后调用,诸如此类。我不得不将我的 res.render 移回到查询回调中。

有正确的方法吗?

最佳答案

您可能想要查看 async 库,例如 https://github.com/caolan/async。它有助于构建异步代码,使其不会变成这样一团糟。根据您的要求,有不同的方法,从简单的 seriesparallel 执行到 waterfallauto 执行依赖跟踪。

async.auto({
get_data: function(callback){
// async code to get some data
},
make_folder: function(callback){
// async code to create a directory to store a file in
// this is run at the same time as getting the data
},
write_file: ['get_data', 'make_folder', function(callback){
// once there is some data and the directory exists,
// write the data to a file in the directory
callback(null, filename);
}],
email_link: ['write_file', function(callback, results){
// once the file is written let's email a link to it...
// results.write_file contains the filename returned by write_file.
}]
}, function(err) {
// everything is done or an error occurred
});

它做的另一件好事是将所有错误合并到一个回调中。这样一来,您只需在一个地方处理错误,而不是将它们散布在整个代码中。

关于node.js - NodeJS 不那么明显的回调和更多的结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12991083/

24 4 0