如何在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
相关产品推荐
相关产品推荐

