You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Inversify中全局获取异步依赖,无需顶层await与重复调用?

解决方案:无需顶层await,一次性获取异步依赖并复用

针对你不想在每个路由中重复调用getService()的需求,以下是三种可行的实现方案:

方案1:用立即执行异步函数(IIFE)预加载Service

在模块加载时通过IIFE一次性获取Service,后续所有路由直接复用该变量,无需重复调用异步方法:

// something.controller.ts
import { Router } from 'express';
const router = Router();

// 立即执行异步函数,一次性获取Service
(async () => {
  const service = await container.getAsync<IService>(TYPES.Service);

  router.get("/collection",
    paginateCollectionSchema,
    validateRequestSchema,
    async (req, res) => {
      const paginationSettings = await service.getSome(req.query.limit, req.query.offset);
      const pagination = paginate("/collection", paginationSettings);
      return res.json(pagination);
    },
  );

  // 其他路由直接复用已获取的service
  router.get("/detail/:id", async (req, res) => {
    const item = await service.getDetail(req.params.id);
    res.json(item);
  });
})();

export default router;

说明:模块加载时会执行该IIFE,提前完成Service的异步获取,后续路由无需重复操作。只要确保Express启动逻辑在路由模块加载完成后执行,就不会出现Service未就绪的问题。

方案2:自定义中间件注入Service到请求上下文

通过中间件将Service挂载到req对象上,所有路由可直接从请求中获取,同时添加缓存避免重复获取:

// something.controller.ts
import { Router } from 'express';
const router = Router();

// 定义注入Service的中间件
const injectService = async (req: any, res: any, next: any) => {
  // 缓存Service,同一个请求仅获取一次
  if (!req.service) {
    req.service = await container.getAsync<IService>(TYPES.Service);
  }
  next();
};

// 给当前路由下的所有接口注入中间件
router.use(injectService);

router.get("/collection",
  paginateCollectionSchema,
  validateRequestSchema,
  async (req, res) => {
    // 直接从req中获取Service
    const paginationSettings = await req.service.getSome(req.query.limit, req.query.offset);
    const pagination = paginate("/collection", paginationSettings);
    return res.json(pagination);
  },
);

router.get("/another-route", async (req, res) => {
  const data = await req.service.getAnotherResource();
  res.json(data);
});

export default router;

说明:该方案适合需要在请求上下文内管理Service实例的场景,若Service是单例模式,缓存后也只会执行一次异步获取操作。

方案3:缓存Service的Promise对象

将getAsync返回的Promise缓存起来,每个路由仅需await该Promise(Promise只会resolve一次,实际仅执行一次异步获取):

// something.controller.ts
import { Router } from 'express';
const router = Router();

// 缓存Service的Promise,仅执行一次getAsync
const servicePromise = container.getAsync<IService>(TYPES.Service);

router.get("/collection",
  paginateCollectionSchema,
  validateRequestSchema,
  async (req, res) => {
    // 每个路由await同一个Promise,实际仅获取一次Service
    const service = await servicePromise;
    const paginationSettings = await service.getSome(req.query.limit, req.query.offset);
    const pagination = paginate("/collection", paginationSettings);
    return res.json(pagination);
  },
);

router.get("/other", async (req, res) => {
  const service = await servicePromise;
  const data = await service.getOtherData();
  res.json(data);
});

export default router;

说明:此方案代码最简洁,适合Service为单例的场景,无需额外包裹路由逻辑,仅通过缓存Promise实现复用。

内容的提问来源于stack exchange,提问作者bik555

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:35:21