【问题标题】:Async Await | Can't have server wait for response from database before using authenification异步等待 |在使用身份验证之前,不能让服务器等待来自数据库的响应
【发布时间】:2019-11-12 10:44:21
【问题描述】:

所以我遇到了一个问题,我试图对我的数据库进行异步调用以检查帐户的用户名和密码是否存在,然后再检查它们是否有效。

我遇到的问题是服务器跳过我的数据库调用,然后在从数据库中获取信息之前进行检查。

代码:

class HandlerGenerator {
  login (req, res) {
    let username = req.body.username;
    let password = req.body.password;
    let checkUsername = "";
    let checkPassword = "";

    var lData = {
        username: req.body.username,
        password: req.body.password
      };
    // For the given username fetch user from DB
    var db = req.db;
    var getUser = async () => {
        var result = await (
          User.findOne(lData , function(err, userLogin){
              if(err){
                console.log(err);
                return
              }
              console.log(userLogin);
              console.log("------====----");
              console.log(userLogin.username);
              checkUsername = userLogin.username;
              checkPassword = userLogin.password;

              console.log("------====----");
              console.log(checkUsername);
              console.log(checkPassword);
            })
        );
        console.log("--00--");
        console.log('result' + result)
        return result;
    };

    console.log("does this work?");
    if (username && password) {
      console.log("------==2==----");
      console.log(checkUsername)
      console.log(checkPassword)
      if (username === checkUsername && password === checkPassword) {
        let token = jwt.sign({username: username},
          config.secret,
          { expiresIn: '24h' // expires in 24 hours
          }
        );
        // return the JWT token for the future API calls
        res.json({
          success: true,
          message: 'Authentication successful!',
          token: token
        });
      } else {
        res.send(403).json({
          success: false,
          message: 'Incorrect username or password'
        });
      }
    } else {
      res.send(400).json({
        success: false,
        message: 'Authentication failed! Please check the request'
      });
    }
  }
  index (req, res) {
    res.json({
      success: true,
      message: 'Index page'
    });
  }
}

当我运行它时,“这行得通吗?”评论总是先运行,我对自己搞砸了什么感到困惑

【问题讨论】:

  • 你不能只是等待,它必须是一个承诺。
  • 你只能await一个promise。
  • 你也只是定义函数,你永远不会调用它或解析结果。
  • 让我做对了,我需要调用 get 用户吗?
  • 我对异步 Promise 还很陌生,您能否快速解释一下?我假设通过设置变量我正在调用它。

标签: javascript express asynchronous async-await


【解决方案1】:

这里有两个主要问题。

首先,async 返回一个 AsyncFunction,它在调用时返回一个 Promise。这意味着此时,getUser 中的任何内容都没有被执行。不仅你需要实际调用getUser 来开始运行其中的内容,而且你还需要等待结果,否则你绝对不能保证执行会结束。 与其经历这个麻烦,不如让你的login 函数async 似乎是一个更合理的选择,因为你正试图在其中进行异步操作。然后,您可以删除 getUser 函数并仅保留 var result = await User.findOne(....) 部分。

正如多个人在 cmets 中所说,另一个问题是您需要在 Promise 上使用 await。 查看您的函数调用,您的 findOne 函数似乎使用回调而不是承诺。请检查文档,一些库支持两者,如果您不传递任何回调,可能确实会返回一个承诺。 如果是这样,则不应传递任何回调。 “等待”调用的结果应该是userLogin

否则,包装函数以使其返回一个承诺很简单。 基本模式如下

// this is the function that we want to wrap
function funcToWrap(someParam, callback) {
   // does stuff
   callback(null, "some result");
}

// this is the wrapper
function wrappedFunction(someParam) {
  return new Promise((resolve, reject) => {
    funcToWrap(someParam, (err, res) => {
      if (err === null) {
        reject(err);
      } else {
        resolve(res);
      }
    });
  });

这会将基于回调的函数转换为基于 Promise 的函数。然后,您当然可以在 wrappedFunc 上使用 await 并将其用作任何其他承诺。

这是一种常见的模式,很多库已经实现了这个功能。例如,Promise 库 Bluebird 提供了一个 promisify 函数,它正是这样做的。 http://bluebirdjs.com/docs/api/promise.promisify.html

所以不用自己写所有这些,你可以简单地写

var wrappedFunction = Promise.promisify(funcToWrap);

【讨论】:

    猜你喜欢
    • 2020-03-06
    • 1970-01-01
    • 2020-07-25
    • 1970-01-01
    • 2022-08-01
    • 1970-01-01
    • 2020-12-03
    • 2018-11-23
    • 2016-01-24
    相关资源
    最近更新 更多