Невозможно передать контекст и параметры в контроллер в express - PullRequest
0 голосов
/ 16 апреля 2020

Я использую сервисную систему контроллера для промежуточного программного обеспечения в express. Я хочу передать переменные в функции промежуточного программного обеспечения, определенные в router. Код зависает, когда достигает функции controller registerUserIfMissing версии 2. Размещение соответствующих частей кода, как показано ниже.

Мой файл контроллера называется index.js

'use strict';

class UserController {

  constructor(UserService) {
    this.userService = UserService;
  };

  // Version 2
  registerUserIfMissing(key) {
    console.log(key);
    return async (req, res, next) => {
      console.log('reached here');
      try {
        const user = req.data.user;
        console.log(user);
        if (!user) {
          console.log('User missing, registering now....');
          const newUser = await this.userService.getUserFromSG(req.params[key]);
          req.body = { ...req.body, ...newUser };
          await this.userService.registerUser(req.body);
        };
        next();
      } catch (e) {
        next(e);
      };
    };
  };

  // Version 1 - needs to be replaced; working now
  async registerUserIfMissing(req, res, next) {
    try {
      const user = req.data.user;
      if (!user) {
        console.log('User missing, registering now....');
        const newUser = await this.userService.getUserFromSG(req.params.user_id);
        req.body = { ...req.body, ...newUser };
        await this.userService.registerUser(req.body);
      };
      next();
    } catch (e) {
      next(e);
    };
  };

};
module.exports = UserController;

Первый файл index.js, который охватывает мой routes

'use strict';

const express = require('express');
const router = express.Router();
const UserController = require('./controllers');
const RegisterUserFacade = require('./services/register-users');
const EditUserFacade = require('./services/edit');
const QueryUserFacade = require('./services/query');
const GoldTxFacade = require('./services/gold-tx');
const SGUserFacade = require('./services/sg-user');
const UserService = require('./services');
const { attachGateway, attachUser } = require('../../middlewares');

const registerUserFacade = new RegisterUserFacade();
const editUserFacade = new EditUserFacade();
const queryUserFacade = new QueryUserFacade();
const goldTxFacade = new GoldTxFacade();
const sgUserFacade = new SGUserFacade();
const userService = new UserService(
  registerUserFacade,
  editUserFacade,
  queryUserFacade,
  goldTxFacade,
  sgUserFacade
);
const controller = new UserController(userService);

router.post(
  '/:user_id/buy-item',
  attachGateway,
  attachUser('user_id'), // this works
  controller.registerUserIfMissing.bind(controller), // this works
  controller.buyGold.bind(controller)
);

// new requirement - does not work !!!
router.post(
  '/:user_id/gift-item/:receiver_id',
  attachGateway,
  attachUser('receiver_id'), // this works
  controller.registerUserIfMissing.bind(controller, 'receiver_id'), // this does not work
  controller.registerUserIfMissing('receiver_id').bind(controller), // this does not work either
  controller.giftGold.bind(controller)
);

module.exports = router;

Код attachUser. Я добавил раздел (key), который позволяет мне напрямую контролировать, к какой части req.params мне нужно получить доступ. После добавления части функции возврата я могу получить доступ к переменным промежуточного программного обеспечения express, поэтому он работает нормально.

const attachUser = (key) => {
  return async (req, res, next) => {
    // retrieve blockchain smart contract ref
    const { contract, gateway } = req.data;
    let user_id = req.params[key];
    // call to blockchain Hyperledger Fabric peer 1
    const ccRres = contract.evaluateTransaction(
      'getUserByID',
      JSON.stringify({ user_id })
    ).then(data => {
      const response = JSON.parse(data.toString());
      req.data.user = response.user;
      next();
    }).catch(e => next(e))
  };
};

module.exports = attachUser;

Я получаю вызов API на buy-gold, где мне нужно проверить, является ли пользователь существует путем вызова attachUser, а затем зарегистрирует его, если он этого не делает, путем вызова registerUserIfMissing, который вызывает внешний API для получения некоторых дополнительных необходимых данных пользователя. Первоначально идентификатор пользователя всегда будет req.params.user_id, но в других вызовах API идентификатор_пользователя передается под другими именами. Первая версия функции жестко кодирует user_id как значение из req.params, но теперь я хочу контролировать, какой ключ он на самом деле использует.

Поскольку мне нужно передать ссылку express на контроллер, нам нужно используйте функцию bind(). Когда я передаю значение ключа в bind, вызов останавливается на контроллере, так как он не может разрешить часть промежуточного программного обеспечения express. Пробовал использовать bind() и apply(), но я не могу понять это.

...