是否可以将回调内部的数据传递给其包装函数?

时间:2019-07-23 20:27:24

标签: javascript mysql node.js function callback

我正在创建一个用户登录系统,需要查询数据库。我是编码的新手,我正努力理解回调以及回调发生后如何传递数据。

我有一个通过回调调用的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)); 
}

2 个答案:

答案 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);
  })

希望这可以帮助其他人在回调和数据上苦苦挣扎。