NestJS
原生支持
NestJS
原生支持请求级别的注入作用域,即实例在每个请求中都会实例化一遍,请求结束后实例销毁。官方文档
在这种注入模式下, Controller
和 Service
中均可以通过如下方式获取到请求实例:
import { Injectable, Scope, Inject } from '@nestjs/common'; import { REQUEST } from '@nestjs/core'; import { Request } from 'express'; @Injectable({ scope: Scope.REQUEST }) export class CatsService { constructor(@Inject(REQUEST) private request: Request) {} }点击复制复制失败已复制
其中 request
属性即是获取到的请求实例。关于此注入模式的详细阐述请转至笔记:NestJS依赖注入
此方案的局限性在于必须是 NestJS
管理的实例才行,超出 NestJS
的实例是无法注入的,例如: Typeorm
的订阅。
引入三方库进行魔改
上述方式已经能在一部分程度上实现上下文功能了,但是依旧有局限,我的场景就是上面提到的 Typeorm
的订阅,只能继续寻找方案了,在 NestJS
仓库中翻看 issue
,能够找到一篇和我的需求场景完全一致的 issue
,issue地址
这篇 issue
中提到三种解决方案,接下来分别介绍这三种解决方案。
Zone.js
由于篇幅有限,关于 Zone.js
库的相关内容请转至笔记:Zone.js
此方案在 NestJS
环境下失败了,原因未知,效果是在中间件中调用了 next
函数后, Zone.current.name
就变成了 <root>
了,而不是我们 fork
的,在其他地方就拿不到内容了,找了半天也没有找到原因。时间关系,暂时放弃,回过头来再搞。
优点
- 此库被
Angular
官方看中,目前已经转移至Angular
仓库下,据说还提议node
原生支持它,但现在也没有看到后续消息 - 下载量可观,截止目前(2021-4-3),
npm
上周下载量达到了200w
- 应用范围广,很多场景均有使用,稳定性得到保障
- 更新速度较其他方案更快(其他方案的包已经三四年没有更新了)
缺点
- 集成失败,这个是致命缺点。。。
cls-hooked
此三方库的 GitHub
地址为:cls-hooked
最终选择的就是这个方案,集成到 NestJS
中运行很好,关于其原理后面有时间再介绍,这里只介绍一下优缺点
优点
- 在
NestJS
项目中表现很好,按照issue
中的操作直接就成功了 - 在
npm
上的下载量也不错,截止目前(2021-4-3),npm
上周下载量达到了82w
缺点
- 是一个老包了,最后一次更新是4年前,似乎版本停滞了
node-request-context
此三方库的 GitHub
地址为:node-request-context
这个是最早我们采用的方案,但是现在不好使了,原因是现在我们采用 node
的最新 LTS
版本,为 14.x
,之前是 10.x
、 12.x
都没有问题。最后定位到原因发现是因为这个包采用了在 node12.x
声明被废弃的 Domain API
官方文档,所以在 node14
中直接就挂了,似乎作者也没有打算继续更新了,此方案直接 pass
吧。
扩展
尽管通过 issue
中给出的三种方案中的一种实现了目的,但是选用的 cls-hooked
这个包更新停滞,这个是我非常害怕的一点,就比如之前用的 node-request-context
一样,用得好好的,然后随着 node
版本的更新迭代,突然就挂了。很担心某一天 cls-hooked
也发生同样的问题,于是顺着这个包的 GitHub
地址去看,发现它 fork
于另一个包—— continuation-local-storage
,此包的地址为:GitHub、npm
cls-hooked
这个包 fork
后的目的主要是在 node8
及其以上的环境中采用 async_hooks
这个原生支持的新 API
,在 node8
之前使用 AsyncWrap
方式。
看来一下 continuation-local-storage
的下载量,在目前(2021-4-3),可以达到周下载量 140w
,最后一次更新是3年前,相比于 cls-hooked
好了一点,但是也没有好太多,既然已经采用了 cls-hooked
实现了需求,也就不换方案了,毕竟这个好处不足以促使我修改方案。