如何将请求对象绑定到node.js中的静态方法

问题描述 投票:0回答:1

我想在我的服务器内实现依赖注入,但有以下限制:

  • 我的 API 应该创建一次,并且是外部的且不可更改
  • 我的 API 公开了一个我可以提供的方法(通过 ctor)
  • 我的 API 希望使用基于请求的数据来记录消息
  • 我用我创建的服务丰富了我的请求
  • 如果有两个同时请求,我希望每个请求都使用自己的请求,并且上下文无法混合
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();
});
javascript node.js typescript express dependency-injection
1个回答
0
投票

您想要的本质上是在 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))
© www.soinside.com 2019 - 2024. All rights reserved.