Vyhledávání na webu

typescript - Angular služba je nedefinovaná v metodě komponenty s vlastním TS dekorátorem


Snažím se přidat vlastní dekorátor metody do funkce komponenty Angular, abych přidal nějakou funkci pro logování.

Metoda komponenty, kterou zdobím, interně volá funkci služby Angular, kterou jsem do komponenty injektoval. Bohužel při spuštění kódu je injektovaná služba detekována jako nedefinovaná.

Níže uvedený ukázkový kód:

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();
  }
}

Způsobuje chybu „Nelze volat someServiceFunction z undefined“. Máte nějaké nápady, jak to rozběhat?

Odpověď č. 1

Pokud okamžitě vrátíte popisovač ze svého dekorátoru, neměli byste používat závorky (). Také kontext this se ztrácí, zkuste použít this, který je v hodnotě popisovače. Kromě toho, když používáte apply, neměli byste používat rozšiřující operátor. Pokud ho chcete použít, musíte použít 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;
}

Odpověď č. 2

Problém, kterému čelíte, je způsoben tím, že uvnitř dekorátoru target je třída, nikoli instance třídy. Dekorátory se aplikují při vytváření třídy, a proto při jejich volání nemohou mít přístup k instanci. K aktuálnímu objektu můžete přistupovat, když je funkce skutečně zavolána:

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