【问题标题】:Mongoose Methods and Typescript - this property is undefinedMongoose 方法和 Typescript - 此属性未定义
【发布时间】:2021-03-25 02:11:32
【问题描述】:

我正在使用 node、express 和 mongoose 开发一个打字稿应用程序一个宁静的 api。

我有一个带有存储功能的身份验证控制器,附加到POST: /api/auth。用户传入他们的电子邮件和密码以将其与散列版本进行比较。

但是 use.model.ts 中的 comparePassword 函数不起作用,因为 this.password 未定义。

auth.controller.ts

import { Request, Response, NextFunction } from 'express';

import User from './../users/user.model';
import jwt from 'jsonwebtoken';
import Config from './../../config/config';

class AuthController {

    private config: any;

    constructor() {

        this.config = new Config();

    }

    public async store(req: Request, res: Response): Promise<any> {

        const input = req.body;

        console.log(input);
        try {

            let user = await User.findOne({ 'email': input.email });

            if (!user) {
                throw {};
            }
            console.log(user);

            user.schema.methods.comparePassword(input.password, (err: any, isMatch: any) => {

                if (err || !isMatch) {

                    return res.status(401).json({
                        success: false,
                        status: 401,
                        data: { err, isMatch },
                        message: 'Authentication Failed, wrong password',
                    });

                }

                if (!err && isMatch) {

                    const token = jwt.sign({ sub: user._id }, this.config.jwt.secretOrKey);

                    return res.status(200).json({
                        success: true,
                        status: 200,
                        data: { user, token },
                        message: 'Authentication Successful',
                    })

                }


            })

        } catch (err) {

            return res.status(404).json({
                success: false,
                status: 404,
                data: err,
                message: 'Failed to Authenticate'
            })

        }


    }
}

export default AuthController;

user.model.ts

import { Schema, Model, Document, model } from 'mongoose';
import bcrypt from 'bcryptjs';
import { UserInterface } from './user.interface';


const UserSchema = new Schema({

    email: {
        type: String,
        required: true
    },
    password: {
        type: String,
        required: true
    },

}, {
        timestamps: { createdAt: 'created_at', updatedAt: 'updated_at' },
    });


UserSchema.pre('save', function (next) {
    let user = <UserInterface>this;
    let SALT_WORK_FACTOR = 10;

    // only hash the password if it has been modified (or is new)
    if (!user.isModified('password')) return next();

    // generate a salt
    bcrypt.genSalt(SALT_WORK_FACTOR, function (err, salt) {
        if (err) return next(err);

        // hash the password using our new salt
        bcrypt.hash(user.password, salt, function (err, hash) {
            if (err) return next(err);

            // override the cleartext password with the hashed one
            user.password = hash;
            next();
        });
    });
});

UserSchema.methods.comparePassword = function (candidatePassword: any, cb: any) {

    //let user = <UserInterface>this;

    console.log(candidatePassword);
    console.log(this.password);

    bcrypt.compare(candidatePassword, this.password, function (err, isMatch) {
        if (err) return cb(err);
        cb(null, isMatch);
    });
};



const User = model<UserInterface>('Users', UserSchema);

export default User;

我有类似的 comparePassword 函数在另一个不使用打字稿的项目中工作。所以我不确定为什么“this”是未定义的并且没有设置为猫鼬用户对象。

【问题讨论】:

  • 我遇到了完全相同的问题 - 您找到解决方案了吗?

标签: node.js typescript express


【解决方案1】:

这是我绕过打字稿问题的方法。

const self:any = this;

用法示例:

UserSchema.methods.comparePassword = function (candidatePassword: any, cb: any) {
    const self:any = this;

    console.log(candidatePassword);
    console.log(self.password);

    bcrypt.compare(candidatePassword, self.password, function (err, isMatch) {
        if (err) return cb(err);
        cb(null, isMatch);
    });
};

此外,如果您赶时间并且不想创建界面,您可以在 pre 事件中执行此操作。

UserSchema.pre<any>('save', function(next) {
   if (!this.isModified('password')) 
       return next();
   ...
})

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2012-12-29
    • 1970-01-01
    • 1970-01-01
    • 2020-04-27
    • 2019-03-23
    • 1970-01-01
    相关资源
    最近更新 更多