我正在创建一个用户登录系统,需要查询数据库。我是编码的新手,我正努力理解回调以及回调发生后如何传递数据。
我有一个通过回调调用的MySQL查询。结果,我需要在下面的异步函数体中使用,以作为在app.js中的使用。异步功能位于路由文件中。
我尝试在回调范围之外创建一个变量,如您在此处看到的,在.query()
之前声明了用户,但在运行后仍收到undefined
。我还尝试在connection.query之前使用关键字await
,以便该函数直到回调完成后才运行,但这似乎也不起作用。
由于我仍在尝试了解JS的工作原理,因此在此刻的任何帮助将不胜感激。谢谢
async function getAll() {
var users;
var query = "SELECT * FROM `users`"; // query database to get
all the players
// execute query
connection.query(query, (err, result) => {
if (err) {
res.redirect('error.ejs');
console.log(error.message);
}
users = result;
});
return users.map(u => {
const { password, ...userWithoutPassword } = u;
return userWithoutPassword;
});
}
下面的函数是在app.js中调用异步函数的地方:
function getAll(req, res, next) {
userService.getAll().then(users => {
console.log(users);
res.json(users)}).catch(err => next(err));
}
答案 0 :(得分:0)
您没有显示正在使用的大量变量,这使我认为您可能使用了不正确的变量。在异步代码(服务器上的特定异步代码)中,不应使用共享或全局变量来处理特定的请求处理程序。如果这样做,您将为并发问题敞开心yourself,其中两个请求相互冲突。这将在服务器中创建很难发现和调试的错误。
在Javascript异步回调中,您可以在回调内部继续进行逻辑流程,因为这是您唯一了解数据值和响应时间的地方。您无需将其分配给更高级别的变量,然后以某种方式在其他范围内使用该数据。这永远不会起作用,因为只有在回调函数内部您才知道该数据何时有效。
此外,仅当您实际上打算在功能内部使用带有承诺的async
时,才需要将功能标记为await
,因此在这种情况下,没有真正理由将功能设为{{1 }},因为您根本没有在数据库中使用Promise。
如果您向我们展示此async
函数如何适合整个请求处理程序的更大上下文,我们可以帮助您更好地设计事物,但是我至少已更改了该函数以传递{{1 }},因此可以在错误案例和成功案例中始终使用它来发送响应。
这是一个基本概念:
getAll()
如果您想传回res
的值或成功/错误,则需要传递一个可以调用的回调,或者需要返回一个可以使用解析后的值以传达该值。
如果您想了解有关返回异步值的更多信息,请参见以下答案:How do I return the response from an asynchronous call?
我的建议是基于承诺的。 mysql2库具有对Promise的内置支持,您需要将它们切换为专用而不是mysql库。我也会完全一致地将响应发送到哪里,无论是错误还是成功:
// method of userService
function getAll(res) {
var query = "SELECT * FROM `users`"; // query database to get all the players
// execute query
connection.query(query, (err, result) => {
if (err) {
res.redirect('error.ejs');
console.log(error.message);
} else {
// do something here to process result from your query
let users = result.map(u => {
// not sure what you're trying to do here
return u.userWithoutPassword;
});
// do something with users here
res.send(...);
}
});
// no code here because this will run BEFORE your query is done
}
// change to pass req to userService.getAll(res)
function getAll(req, res, next) {
userService.getAll(res);
}
答案 1 :(得分:0)
好吧,我想我终于设法仅使用回调解决了我的问题。如果有人可以帮助我,现在最好将其发展为使用诺言。但是,这是我的最终产品(可以将其拆开):
grabUsers()
函数开始查询,然后将数据传递到回调函数中,以在下一个回调中使用。
function grabUsers(callback){
var query = "SELECT * FROM `users`"; // query database to get all the
players
// execute query
connection.query(query, (err, result) => {
if (err) {
res.redirect('error.ejs');
console.log(error.message);
}
let users = result;
callback(null, users);
})
}
然后,getAll函数使用grabUsers()
回调来处理数据。
function getAll(callback) {
grabUsers(function(err, users){
if (err) {
res.redirect('error.ejs');
console.log(error.message);
}
users = users.map(u => {
const { password, ...userWithoutPassword } = u;
return userWithoutPassword;
});
callback(null, users);
});
}
app.js上的最终getAll函数随后对代码进行了一些最终处理,而无需使用回调参数,因为这是链中函数的最底层。
function getAll(req, res, next) {
userService.getAll(function(err,users){
if (err) {
res.redirect('error.ejs');
console.log(error.message);
}
res.json(users);
console.log(users);
})
希望这可以帮助其他人在回调和数据上苦苦挣扎。