javascript - 在基于组件的结构中注入服务依赖
问题描述
我遵循模块化或基于组件的结构。我找到了一个示例回购。
https://github.com/sujeet-agrahari/node-express-clean-architecture
因此,有一个主要的 component.module.js 文件负责连接所有其他部分,如控制器、路由和服务。
对于控制器,服务是使用高阶函数注入的。现在,控制器超级容易测试,我可以轻松地存根或模拟服务。
auth.module.js
const router = require('express').Router();
const {
makeExpressCallback,
makeValidatorCallback,
} = require('../../middlewares');
// validator
const AuthValidator = require('./auth.validator');
// service
const { doRegister, doLogin, doCheckUserExist } = require('./auth.service');
const { BadRequestError } = require('../../utils/api-errors');
// controller
const controller = require('./auth.controller');
const register = controller.register({ BadRequestError, doCheckUserExist, doRegister });
const login = controller.login({ doCheckUserExist, doLogin });
const AuthController = { register, login };
// routes
const routes = require('./auth.routes')({
router,
AuthController,
AuthValidator,
makeValidatorCallback,
makeExpressCallback,
});
module.exports = {
AuthController,
AuthService: {
doCheckUserExist,
doLogin,
doRegister,
},
AuthRoutes: routes,
};
auth.controller.js
const login = (doCheckUserExist, doLogin) => async (httpRequest) => {
const { username, password } = httpRequest.body;
const userData = await doCheckUserExist({ username });
const loginData = {
username,
role: userData.role_id,
passedPassword: password,
actualPassword: userData.password,
};
const loginResult = await doLogin(loginData);
return {
statusCode: 200,
body: {
success: true,
message: 'Successfully logged in!',
data: loginResult,
},
};
};
const register = ({ BadRequestError, doCheckUserExist, doRegister }) => async (httpRequest) => {
const { username, password } = httpRequest.body;
try {
await doCheckUserExist({ username });
} catch (error) {
// user doesn't exist
const registerResult = await doRegister({ username, password });
return {
statusCode: 200,
body: {
success: true,
message: 'Registered successfully!',
data: registerResult,
},
};
}
throw new BadRequestError('User already exist!');
};
module.exports = { register, login };
控制器一切正常,现在问题出在服务上。我找不到任何图案让它们变得又薄又干净。
auth.services.js
const {
JWT_ACCESS_TOKEN_SECRET,
ACCESS_TOKEN_EXPIRES_IN,
SIGN_OPTION,
} = require('config');
const bcrypt = require('bcryptjs');
const { User } = require('../../db');
const { generateJWT } = require('./jwt.service');
const { NotFoundError, BadRequestError } = require('../../utils/api-errors');
const doRegister = async ({ username, password }) => {
const user = await User.create({
username,
password,
role_id: 1, // assign role id here
});
// generate access token
const payload = {
username,
role: user.role_id,
};
const token = await generateJWT({
secretKey: JWT_ACCESS_TOKEN_SECRET,
payload,
signOption: {
...SIGN_OPTION,
expiresIn: ACCESS_TOKEN_EXPIRES_IN,
},
});
return {
access_token: token,
...payload,
};
};
const doLogin = async ({
username, userRole, passedPassword, actualPassword,
}) => {
const isValidPass = bcrypt.compareSync(passedPassword, actualPassword);
if (!isValidPass) throw new BadRequestError('Username or Password is invalid!');
// generate access token
const payload = {
username,
role: userRole,
};
const token = await generateJWT({
secretKey: JWT_ACCESS_TOKEN_SECRET,
payload,
signOption: {
...SIGN_OPTION,
expiresIn: ACCESS_TOKEN_EXPIRES_IN,
},
});
return {
access_token: token,
...payload,
};
};
const doCheckUserExist = async ({ username }) => {
const user = await User.findOne({
where: {
username,
},
});
if (!user) throw new NotFoundError('User not found!');
return user;
};
module.exports = { doRegister, doLogin, doCheckUserExist };
在服务、模型导入、常量导入和其他实用程序中发生了很多事情。
现在服务变得很难测试。
有什么方法或模式可以将一些逻辑与服务分开并使它们更轻吗?
我可以为 db 方法实现存储模式,但我不知道如何使用 sequelize 实现?
我是否也应该使用高阶函数来注入服务中的所有实用程序和常量,就像我为控制器所做的那样?
解决方案
推荐阅读
- oauth - 是否可以在 Azure Active Directory 的应用程序注册中设置固定范围/资源,而不是让客户端提供这个?
- amazon-web-services - AWS 上的 SSL 安装
- spring-boot - spring zuul中基于严格匹配的路由匹配
- python - 使用 lstm 进行 imdb 评论获得非常低的准确性
- ios - 模拟中的子视图没有那么大
- kubernetes - Sole Tiller 在 Kubernetes 上部署多个命名空间
- javascript - 无需页面重新加载的页面导航 Zend 框架
- node.js - ReactDOM.render:React 从 16.4.2 升级到 16.5.2 后,无法在未安装的组件上找到节点
- java - 无法解析的依赖 org.springframework.core.KotlinDetector.isKotlinReflectPresent()z
- eclipse - Subclipse 在 SVN 访问时使 eclipse photon 崩溃