warning 警告 本章仅适用于代码优先方法。
字段中间件允许你在字段解析之前或之后运行任意代码。字段中间件可用于转换字段结果、验证字段参数,甚至检查字段级别的角色(例如,访问目标字段所需的权限,中间件函数将为此执行)。
你可以为一个字段连接多个中间件函数。在这种情况下,它们将沿着链依次调用,前一个中间件决定是否调用下一个。在 middleware
数组中,中间件函数的顺序很重要。第一个解析器是"最外层",因此它最先执行且最后结束(类似于 graphql-middleware
包)。第二个解析器是"次外层",因此它第二个执行且倒数第二个结束。
让我们从创建一个简单的中间件开始,该中间件将在字段值返回给客户端之前记录它:
info 提示
MiddlewareContext
是一个包含与 GraphQL 解析器函数通常接收的相同参数的对象 ({{ '{' }} source, args, context, info {{ '}' }}
),而NextFn
是一个允许您执行堆栈中下一个中间件(绑定到此字段)或实际字段解析器的函数。
warning 注意 字段中间件函数无法注入依赖项也无法访问 Nest 的 DI 容器,因为它们被设计得非常轻量级且不应执行任何可能耗时的操作(如从数据库检索数据)。如果您需要调用外部服务/从数据源查询数据,应在绑定到根查询/变更处理程序的守卫/拦截器中完成,并将其分配给可从字段中间件内部(特别是从
MiddlewareContext
对象中)访问的context
对象。
请注意,字段中间件必须符合 FieldMiddleware
接口规范。在上述示例中,我们先执行 next()
函数(该函数会执行实际的字段解析器并返回字段值),然后将该值记录到终端。此外,中间件函数返回的值会完全覆盖之前的值,由于我们不希望进行任何修改,因此直接返回原始值。
完成这些后,我们可以直接在 @Field()
装饰器中注册中间件,如下所示:
现在每当我们请求 Recipe
对象类型的 title
字段时,原始字段值将被记录到控制台。
提示 要了解如何通过 extensions 功能实现字段级权限系统,请查看此章节 。
warning 警告 字段中间件只能应用于
ObjectType
类。更多详情请查看此 问题 。
此外,如上所述,我们可以在中间件函数内部控制字段值。出于演示目的,我们将食谱标题(如果存在)转换为大写:
在这种情况下,每当请求时,每个标题都会自动转换为大写。
同样地,您可以将字段中间件绑定到自定义字段解析器(使用 @ResolveField()
装饰器注解的方法),如下所示:
warning 警告 如果在字段解析器级别启用了增强器( 了解更多 ),字段中间件函数将在任何拦截器、守卫等绑定到方法之前运行(但在为查询或变更处理程序注册的根级别增强器之后)。
除了直接将中间件绑定到特定字段外,您还可以全局注册一个或多个中间件函数。在这种情况下,它们将自动连接到您对象类型的所有字段。
info 提示 全局注册的字段中间件函数将在本地注册的中间件(直接绑定到特定字段的那些) 之前执行。