我在带有 Express 的项目中使用 Inversify.JS。我想创建一个到 Neo4J 数据库的连接,这个过程有两个对象:
- 驱动程序对象 - 可以在整个应用程序中共享并且只创建一次
- session对象——每个HTTP请求都应该针对driver创建一个session,其生命周期与http请求的生命周期相同(只要请求结束,连接就被销毁)
如果没有 Insersify.JS,这个问题可以用一个简单的算法解决:
exports.getSession = function (context) { // 'context' is the http request
if(context.neo4jSession) {
return context.neo4jSession;
}
else {
context.neo4jSession = driver.session();
return context.neo4jSession;
}
};
(示例:https://github.com/neo4j-examples/neo4j-movies-template/blob/master/api/neo4j/dbUtils.js#L13-L21)
要为驱动程序创建静态依赖项,我可以注入(inject)一个常量:
container.bind<DbDriver>("DbDriver").toConstantValue(new Neo4JDbDriver());
我如何创建一个仅每个请求实例化一次的依赖项并从容器中检索它们?
我怀疑我必须像这样在中间件上调用容器:
this._express.use((request, response, next) => {
// get the container and create an instance of the Neo4JSession for the request lifecycle
next();
});
提前致谢。
最佳答案
我看到有两种方法可以解决您的问题。
- 使用
inRequestScope()
作为DbDriver
依赖项。 (自 4.5.0 版本起可用)。如果您对一个 http 请求使用单个组合根,它将起作用。换句话说,对于每个 http 请求,您只调用一次container.get()
。 创建子容器,将其附加到
response.locals._container
并将DbDriver
注册为单例。let appContainer = new Container() appContainer.bind(SomeDependencySymbol).to(SomeDependencyImpl); function injectContainerMiddleware(request, response, next) { let requestContainer = appContainer.createChildContainer(); requestContainer.bind<DbDriver>("DbDriver").toConstantValue(new Neo4JDbDriver()); response.locals._container = requestContainer; next(); } express.use(injectContainerMiddleware); //insert injectContainerMiddleware before any other request handler functions
在此示例中,您可以在 injectContainerMiddleware
之后注册的任何请求处理程序/中间件函数中从 response.locals._container
检索 DbDriver
,您将获取相同的 DbDriver
这会起作用,但我不确定它的性能如何。此外,我猜你可能需要在 http 请求完成后以某种方式处理 requestContainer
(取消绑定(bind)所有依赖项并删除对父容器的引用)。
关于express - InversifyJS:每个 HTTP 请求的依赖实例化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45378966/