Así que estoy teniendo un problema en el que estoy intentando tener una llamada de ASYNC a mi base de datos para verificar si existen el nombre de usuario y la contraseña de una cuenta antes de verificar si son válidos.

Me estoy quedando con el problema de que el servidor salta la llamada de mi base de datos y luego se realiza a la verificación antes de que se agarra la información de la base de datos.

El código:

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'
    });
  }
}

Cuando ejecuto esto, "¿Esto funciona?" Comentario siempre se ejecuta primero y estoy confundido en lo que estoy arruinando

-3
Echo 1 jul. 2019 a las 22:27

1 respuesta

La mejor respuesta

Tienes dos problemas principales aquí.

Primero, async devuelve un AsyncFunction, que devuelve un Promise cuando se llama. Esto significa que en este punto, nada en getUser ha sido ejecutado. No solo necesita llamar a getUser para comenzar a ejecutar lo que está dentro de él, pero también debe esperar el resultado, de lo contrario no tiene ninguna garantía de que la ejecución haya terminado. En lugar de pasar por este problema, la función login async parece una opción más razonable, ya que está tratando de hacer operaciones asíncronas dentro de ella. Luego, podría eliminar la función getUser y solo mantener la parte var result = await User.findOne(....).

El otro problema, como dijeron múltiples personas en los comentarios, es que necesita await en un Promise. Mirando su llamada de función, parece que sus funciones findOne usan una devolución de llamada en lugar de una promesa. Verifique la documentación, algunas bibliotecas admiten ambas y, de hecho, podrían devolver una promesa si no pasa en ninguna devolución de llamada. Si lo hace, no debe pasar ninguna devolución de llamada. El resultado de la llamada "esperada" debe ser userLogin.

De lo contrario, envolviendo la función para que devuelva una promesa es sencilla. El patrón básico es el siguiente.

// 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);
      }
    });
  });

Esto transforma su función basada en devolución de llamada en una promesa basada en la promesa. Luego, puede, por supuesto, await en wrappedFunc y uselo como cualquier otra promesa.

Este es un patrón tan común que muchas bibliotecas ya implementan esta funcionalidad. Por ejemplo, la biblioteca Promise Bluebird proporciona una función promisify que hace exactamente esto. http://bluebirdjs.com/docs/api/promise.promisify.html

Así que en lugar de escribir todo esto usted mismo, simplemente podrías escribir

var wrappedFunction = Promise.promisify(funcToWrap);
1
Daniel Perez 1 jul. 2019 a las 20:45