Я использую сервисную систему контроллера для промежуточного программного обеспечения в 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()
, но я не могу понять это.