2

我在 Express 项目中使用 Inversify.JS。我想创建一个到 Neo4J 数据库的连接,这个过程有两个对象:

  1. 驱动程序对象 - 可以在应用程序之间共享并且只创建一次
  2. session 对象 - 每个 HTTP 请求都应该针对驱动创建一个会话,其生命周期与 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 )

要为驱动程序创建静态依赖项,我可以注入一个常量:

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();
});

提前致谢。

4

1 回答 1

1

我看到您的问题有两种解决方案。

  1. 用于依赖inRequestScope()DbDriver(从 4.5.0 版本开始可用)。如果您对一个 http 请求使用单个组合根,它将起作用。换句话说,container.get()每个 http 请求只调用一次。
  2. 创建子容器,将其附加到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
    

在此示例中,您可以DbDriverresponse.locals._container之后注册的任何请求处理程序/中间件函数中检索injectContainerMiddleware,您将获得相同的实例DbDriver

这会起作用,但我不确定它的性能如何。此外,我猜您可能需要requestContainer在 http 请求完成后以某种方式处理(取消绑定所有依赖项并删除对父容器的引用)。

于 2017-12-07T22:30:20.763 回答