我想在我的服务器内实现依赖注入,但有以下限制:
function createApi() {
function logMessage(msg: string) {
logger.log(req.url, req.sessionId, msg);
}
const api = new ExternalApi({ logMessage });
return { api };
}
我想用来丰富请求的节点中间件:
import { RequestHandler, Request } from 'express';
export const bootstrapRequestContext = (): RequestHandler => {
const { api } = createApi();
return (request: Request, _, next) => {
request.api = api.bind(request); // ??
next();
};
};
我的路由器内部:
router.get('some-url/', (request) => {
request.api.doSomething();
});
您想要的本质上是在 API 实体中使用请求实体,并在请求实体中使用 API 实体;像这样的东西:
req.api = new API(req)
这种模式称为循环依赖,众所周知,它会导致内存泄漏(循环引用导致内存泄漏?) - 由于值始终指向彼此,垃圾收集器无法知道这些值何时变得未使用。您可以通过取消引用变量(
delete req.api
或req.api = null
)来修复它,但最好一开始就不要引入它。
要在不引入内存泄漏的情况下回答您的具体问题,请考虑关注点分离。简而言之,您定义的服务不依赖于
req
和 res
对象,而只是输入输出函数的集合,如下所示:
class UsersService {
getUserById(userId: string): User | null {
return users[userId] ?? null
}
// …
}
...然后使用这些实例来创建请求处理程序:
import { type RequestHandler } from 'express'
function createGetUserController(usersService: UsersService): RequestHandler {
return (req, res) => {
const userId = req.params.user_id
const user = userService.getUserById(userId)
if (user != null) {
res.status(200).json(user)
} else {
res.sendStatus(404)
}
}
}
const usersService = new UsersService()
app.get("/users/:user_id", createGetUserController(usersService))