网站搜索

typescript - 使用自定义 TS 装饰器时,Angular 服务在组件方法中未定义


我正在尝试向 Angular 组件函数添加自定义方法装饰器,以添加一些日志功能。

我正在装饰的组件方法内部调用了一个我注入到组件中的 Angular 服务函数。不幸的是,在运行代码时,注入的服务被认为是未定义的。

下面的示例代码:

function myCustomDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalValue = descriptor.value;
  descriptor.value = function(...args: any[]) {
    const result = originalValue.apply(target, ...args);
    //Do some other stuff
    return result;
  }
  return descriptor;
}

@Component()
class myComponentClass implements OnInit {
  constructor(private myService: MyService) {}

  ngOnInit() {
    this.functionIWantToDecorate();
  }

  @myCustomDecorator
  private functionIWantToDecorate() {
    this.myService.someServiceFunction();
  }
}

会导致“无法调用未定义的 someServiceFunction”错误。有谁知道如何解决这个问题吗?

答案#1

如果你立即从装饰器返回一个描述符,你不应该使用大括号()。此外,this上下文会丢失,尝试使用在描述符值中的this。除此之外,当你使用apply时,你不应该使用扩展运算符。如果你想使用它,你必须使用call:

function myCustomDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalValue = descriptor.value;
  descriptor.value = function(this: Function, ...args: any[]) {
    const result = originalValue.call(this, ...args);
    // or --> const result = originalValue.apply(this, args);
    //Do some other stuff
    return result;
  }
  return descriptor;
}

答案#2

你面临的问题是由于在装饰器target内部是类而不是类的实例造成的。装饰器是在类创建时应用的,因此在调用它们时无法访问实例。当函数实际被调用时,你可以访问当前对象:

descriptor.value = function(...args: any[]) {
  const result = originalValue.apply(this, ...args); // this not target 
  //Do some other stuff
  return result;
}