我一直在开发一个lambda项目,我们使用lambda-api包。然后我定义了一些名为Get
和Post
的装饰器来将路由Map到lambda API对象。使用这些装饰器,我定义了一个名为ProductApi的类来保存可以使用这些装饰器配置并传递路由路径的方法。它工作得很好。
问题是,当我有一个像ProductApi
这样的类时,构造函数永远不会被调用,如果我想添加一些依赖项(比如Service或Repository),它永远不会被定义。在这个例子中,/health
路由工作得很好,因为它不使用对象示例中的任何东西,但其他路由不使用。
如何确保构造函数将被调用并定义服务示例?
const api = createAPI();
function Get(path: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
api.get(path, descriptor.value.bind(target));
};
}
function Post(path: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
api.post(path, descriptor.value.bind(target));
};
}
class ProductApi {
private someValue: string;
constructor(private readonly productService: IProductService = new ProductService()) {
// this scope does not execute
this.someValue = "some value";
}
@Get('/health')
async healthCheckr(req: Request, res: Response) {
console.log(`Executing -- GET /health`);
// this.someValue does not exists here
return res.status(200).json({ ok: true });
}
@Get('/products')
async getProducts(req: Request, res: Response) {
console.log(`Executing -- GET /products`);
const data = this.productService.getProductsFromService(); // error: Cannot read properties of undefined (reading 'getProductsFromService')
return res.status(200).json(data);
}
@Post('/products')
async postProducts(req: Request, res: Response) {
console.log(`Executing -- POST /products`);
const product = this.productService.saveProduct('Drums', 1200); // erro: Cannot read properties of undefined (reading 'saveProduct')
return res.status(201).json(product);
}
}
export const lambdaHandler = async (event: APIGatewayProxyEvent, context: Context): Promise<APIGatewayProxyResult> => {
console.log('SCOPE lambda');
return await api.run(event, context);
};
注意:我不想使用框架,我只想在lamda API示例上配置路由的简单方法。
2条答案
按热度按时间ccrfmcuu1#
与C#不同,在JS中,“方法”只是一个固定在对象上的函数。你可以很容易地将它放在一个变量中,或者将它固定在另一个对象上。这基本上定义了“方法”中的
this
。而“类”构造函数只是一个创建新对象的函数,并告诉它,“如果有人在寻找你没有的属性,然后,它将该对象作为this
执行构造函数中的代码。简单地说,这就是JS的原型继承,即使JS在此期间接收了
class
关键字,这仍然是幕后发生的事情。我为什么要解释这个?
这一行
api.get(path, descriptor.value.bind(target));
从原型中获取方法,将原型对象永久绑定为this
(因此结果函数将只知道原型对象,永远不会看到任何真实的示例) 并使用绑定函数作为该路由的回调。所以目前,即使那个类会神奇地被示例化(由谁;我不知道)你传递给路由的函数将不知道这一点。
imo.你的装饰器应该看起来更像这样:
侧记:迪玛瓦提出了这个主题;这些都是遗留的装饰器。TS在JS中有装饰器规范之前很久就适应了它们。现在有了一个,它与这些遗留的装饰器有很大的不同,TS最终在V5中实现了规范。你(和我)应该更新新的语法并采用它,因为这种语法可能很快就会被弃用。
a7qyws3x2#
您需要首先存储有关如何绑定路由的元数据,然后在创建类时应用它
https://tsplay.dev/mbvA4m(可运行)