我对NestJs如何成功创建其控制器非常感兴趣。例如,我可以在NestJs控制器中执行此操作。
@Controller('/mycontroller')
class MyController {
@Post()
createItemRoute(
@Query() myQuery: myQueryDto,
@Body() body: bodyDto,
@Res() res: Response
// I can add more parameters to here if I want or have a different set of parameters in another method
) {
console.log('Query:', myQuery)
console.log('Body:', body)
console.log('Response:', res)
}
}
我基本上可以在createItemRoute
中添加任意数量的参数。对参数进行修饰,并使用修饰后的参数很好地处理了参数中的最终值,供我使用。
由于NestJs使用Express,因此我假设createItemRoute
是通过标准Express req
,res
,next
参数传递的,然后进一步传递给修饰的处理参数。
我很好奇这是如何完成的,因此决定尝试在练习中复制相同的效果,但是我不知道该如何实现。这是我到目前为止的内容:
function Post() {
return function (target: Record<string, any>, key: string, descriptor: PropertyDescriptor) {
const original: Function = descriptor.value;
// 1. To get the arguments of the original method
const originalArguments = descriptor.value.arguments; // But this causes an error that arguments cannot be used
// 2. Changes the original method's signature to receive from Express just as an ordinary middleware function
descriptor.value = function(req: Request, res: Response) {
const newArguments = []
// 3. To loop through the arguments retrieved and apply them
for (const param in originalArguments) { // This fails too because I couldn't retrieve the arguments into originalArguments in the previous line
newArguments.push(param(req, res)) // Somehow passes the req and res into the decorated arguments of the original method for them to process and return their processed values
}
originalMethod.apply(this, newArguments). // Then apply with the new arguments
}
return descriptor;
}
}
// 5. The @Body() decorator which returns a function so that it can be used in the Post() decorator
function Body() {
return function (target: Record<string, any>, key: string, descriptor: PropertyDescriptor) {
return (req, res) => {
return res.body
}
}
}
const testMyController = new MyController();
const mockReq = { body: 'my body content' }
const mockRes = { status: (code) => true }
// 4. Assuming Express will pass its req and res into the function
testMyController.createItemRoute(mockReq, mockRes) // This will cause Typescript to throw an error that the method signature mismatches the one created in MyController
在我尝试过的过程中,想法是通过装饰器将createItemRoute
中的MyController
包装在另一个函数中,该装饰器可用于从Express接收参数。但是,我在示例代码中将它们标记为几个问题。
由于我可以在控制器方法(createItemRoute
)中添加任意数量的参数,因此需要一种方法来检索数组中的参数。该方法未使用...args
声明,因此我不能直接获取它们。使用descriptor.value.arguments
还会引发不允许的错误。我希望能一直保持严格的状态。
我将原始方法的签名转换为适合典型Express中间件的形状,以便以后可以将其作为中间件传递给Express。这不起作用,我们将在后面的步骤4中看到。
由于有多个装饰参数传递到createItemRoute
中,因此我需要遍历它们,并为它们提供Express中的原始req
和res
,以便装饰器可以处理它们并返回它们的值。但是,这里有几个问题。
req
和res
传递给装饰器。我拥有param(req, res)
的那部分似乎也不起作用。因此,由于我已经通过装饰器转换了createItemRoute
的方法签名,所以我认为我可以开始从Express接收req和res值了。我嘲笑了req
和res
,并试图将它们传递到createItemRoute
方法中。但是,由于我使用的是Typescript,它将开始抱怨并引发有关方法签名不匹配的错误!
在@Body
装饰器中,我计划在步骤#3中以某种方式从@Post
装饰器接收请求和资源。但这显然似乎行不通。
我需要帮助来阐明如何实现控制器在NestJs中的工作方式。