Рефакторированное промежуточное ПО Express дает «не могу установить свойство неопределенным» - PullRequest
0 голосов
/ 18 мая 2019

Я пытаюсь провести рефакторинг промежуточного программного обеспечения в моих маршрутах Express в соответствии с рекомендациями CodeClimate, чтобы избежать дублирования кода, но реорганизованный код выдает TypeError: Cannot set property "checkUser" of undefined, если я использую свойство this в методе статического класса

Я использую PostgreSQL, pg-обещание, bcrypt и jwt в своем приложении Express

Модуль для абстрагирования моего промежуточного ПО

  static routeCallbacks(...methods) {
    const callbacks = methods.map(method => (...args) => {
      method(...args);
    });
    return callbacks;
  }
}

Абстрактное промежуточное ПО

import validateUserRequest from '../data/users';
import authenticateUsers from '../auth/users';
import middleware from './middleware';

export default class Users {
...

   static signinClients() {
    const signin = middleware.routeCallbacks(validateUserRequest.signIn, authenticateUsers.signIn);
    return signin;
  }

...
}

вспомогательные методы сверху

import protocol from '../helpers/response';
import checkRequest from '../helpers/checkRequest';

export default class ValidateUserRequest {
...

 static signIn(req, res, next) {
    const { userEmail, userPassword } = req.body;
    const emailErr = checkRequest.checkEmailFormat(userEmail, 'Email');
    const passwordErr = checkRequest.checkPassword(userPassword, 'Password');
    const findError = checkRequest.findError(emailErr, passwordErr);
    if (findError) protocol.err400Res(res, findError);
    else next();
  }

...
}

import database from '../db/pgConnect';
import protocol from '../helpers/response';
import queries from '../helpers/queries';

export default class AuthenticateUsers {
...

  static async signIn(req, res, next) {
    const { userEmail } = req.body;
    const checkUserQuery = queries.findClientByEmail();
    this.checkUser = await database.queryOneORNone(checkUserQuery, [userEmail]);
    if (!this.checkUser) return protocol.err404Res(res, errors.userNotExists('User'));
    return next();
  }

...
}

контроллер после промежуточного программного обеспечения

import database from '../db/pgConnect';
import password from '../helpers/bcrypt';
import token from '../helpers/jwt';
import authenticateUsers from '../auth/users';
import protocol from '../helpers/response';
import errors from '../helpers/errorMessage';
import models from '../models/users';
import queries from '../helpers/queries';

export default class Users {
...

 static async signIn(req, res) {
    const { userPassword } = req.body;
    const { checkUser } = authenticateUsers;
    const verifyPassword = await password.compare(checkUser.password, userPassword);
    if (!verifyPassword) return protocol.err400Res(res, errors.wrongPassword());
    const signInRes = await models.createUserDataResPostgre(checkUser);
    const newToken = await token.generate(checkUser.id);
    return protocol.auth200Res(res, signInRes, newToken);
  }

...
}

Мои маршруты (после рефакторинга дает невозможно установить свойство checkUser неопределенной ошибки)

import userController from '../controllers/users';
import router from './router';
import userMiddleware from '../middleware/users';

router.post('/auth/signin', userMiddleware.signinClients(), userController.signIn);

...
export default router;

Мои маршруты (до рефакторинга нормально работает)

import userController from '../controllers/users';
import router from './router';
import userMiddleware from '../middleware/users';

router.post('/auth/signin', (...args) => { validateUserRequest.signIn(...args) }, 
(...args) => { authenticateUsers.signIn(...args) }, userController.signIn);

...
export default router;

Поскольку код, по сути, такой же, за исключением простого рефакторинга, я должен получить код состояния 200, а не 500

1 Ответ

0 голосов
/ 18 мая 2019

Проблема в том, что this в вашем AuthenticateUsers классе не привязан к вашему классу и поэтому не определен.Таким образом, вместо прямой передачи функций signIn, свяжите их с соответствующими классами:

const signin = middleware.routeCallbacks(validateUserRequest.signIn.bind(validateUserRequest), authenticateUsers.signIn.bind(authenticateUsers));

Может быть, сначала рассмотрим этот простой пример:

class TestClass {
    static test() {
        try {
            console.log(this);
            this.tmpData = "some data";
            console.log(this.tmpData);
        } catch (err) {
            console.log("caught error: " + err);
        }
    }
}

const fn = TestClass.test;
console.log("invoking unbound fn:");
fn();
console.log("------------------------------");
const fnBound = TestClass.test.bind(TestClass);
console.log("invoking bound fn:");
fnBound();

Это выведет:

invoking unbound fn:
undefined
caught error: TypeError: Cannot set property 'tmpData' of undefined
------------------------------
invoking bound fn:
[Function: TestClass]
some data
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...