首页 > 解决方案 > 从 Express Router 中分离 Mongoose 代码

问题描述

所以基本上,我试图将处理数据(猫鼬)的代码与我的快速路由器代码分开,因为我可能也想在其他地方使用它。

我做的第一件事是,我摆脱了 res.json() 调用,因为我不希望代码只返回一个 http 响应。我希望它返回数据,因此我可以从路由器返回该数据作为 http 响应,但仍将其用作其他地方的常规数据。

这是我编写的用于从 mongoose 获取数据的函数。

module.exports.user_login = data => {
    console.log(data);
    ModelUser.findOne({email: data.email}).then(user => {
        if(!user){
            console.log({email: 'E-mail address not found'});
            return {
                status: response_code.HTTP_404,
                response: {email: 'E-mail address not found'}
            }
        }

        bcrypt.compare(data.password, user.password).then(isMatch => {
            if(!isMatch){
                console.log({password: 'Invalid password'});
                return {
                    status: response_code.HTTP_400,
                    response: {password: 'Invalid password'}
                }
            }
                
            const payload = {
                id: user.id,
                email: user.email
            };

            jwt.sign(
                payload,
                config.PASSPORT_SECRET,
                { 
                    expiresIn: "1h"
                },
                (err, token) => {
                    console.log({
                        status: response_code.HTTP_200,
                        response: {
                            success: true,
                            token: token
                        }
                    });
                    return {
                        status: response_code.HTTP_200,
                        response: {
                            success: true,
                            token: token
                        }
                    }
                }
            );
        });
    });
};

当此代码在我的路线中执行时,如下所示:

router.post("/login", (req, res) => {
    const { errors, isValid } = validateLogin(req.body);
    if(!isValid) return res.status(400).json(errors);

    console.log("ret", dm_user.user_login(req.body));
    
});

日志说 user_login() 的返回值是未定义的,即使在 user_login() 中的 return 语句之前我正在记录完全相同的值并且它们正在被记录。

在我将它更改为日志之前,我尝试将返回值存储在一个变量中,但显然它仍然是未定义的,并且我收到错误:尝试使用该值时无法读取未定义的属性“状态”。

我肯定错过了一些东西..

标签: javascriptnode.jsasynchronous

解决方案


好吧,这里有一个小的回调地狱。async / await将代码拆分成更小的块而不是将所有内容放在一个文件中可能是个好主意。

我重写了你的user_login函数:

const { generateToken } = require("./token.js");
module.exports.user_login = async data => {
  let user = await ModelUser.findOne({ email: data.email });
  if (!user) {
    console.log({ email: "E-mail address not found" });
    return {
      status: response_code.HTTP_404,
      response: { email: "E-mail address not found" }
    };
  }

  let isMatch = await bcrypt.compare(data.password, user.password);
  if (!isMatch) {
    console.log({ password: "Invalid password" });
    return {
      status: response_code.HTTP_400,
      response: { password: "Invalid password" }
    };
  }

  const payload = {
    id: user.id,
    email: user.email
  };

  let response = await generateToken(
    payload,
    config.PASSPORT_SECRET,
    response_code
  );
  return response;
};

我已将您的令牌签名方法移至另一个文件并承诺:

module.exports.generateToken = (payload, secret, response_code) => {
  return new Promise((res, rej) => {
    jwt.sign(
      payload,
      secret,
      {
        expiresIn: "1h"
      },
      (err, token) => {
        if (err) {
          rej(err);
        }
        res({
          status: response_code.HTTP_200,
          response: {
            success: true,
            token: token
          }
        });
      }
    );
  });
};

现在您需要将路由器功能更改为异步:

router.post("/login", async (req, res) => {
    const { errors, isValid } = validateLogin(req.body);
    if(!isValid) return res.status(400).json(errors);

    let result = await dm_user.user_login(req.body);
    console.log(result);
    
});

另外:你得到 undefined 因为你将你的值返回给一个回调函数

我还将您的路由与您的控制器分开,而不是在匿名函数中编写代码


推荐阅读