Angular에서 디바운싱 구성 요소 메서드

구성 요소 메서드를 사용하는 것은 일반적으로 알려진 이유로 현명하지 않지만 때로는 응용 프로그램에 출력에 반응하기 위해 템플릿에서 구성 요소 메서드를 사용해야 하는 타사 구성 요소가 있을 수 있습니다.

오늘의 기사에서는 구성 요소의 메서드 실행을 디바운싱하는 방법을 탐색하여 rxjs 도구를 확인하지 않고 너무 자주 실행되지 않도록 합니다.

단순화를 위해 카운터를 구현하는 간단한 구성 요소를 사용합니다.

import { Component } from '@angular/core';

@Component({
  template: `<p>{{ calledTimes }}</p>
    <p><button (click)="increment()">increment</button></p>`,
  selector: 'app-root',
})
export class AppComponent {
  private _calledTimes = 0;

  public get calledTimes(): number {
    return this._calledTimes;
  }

  public increment(): void {
    this._calledTimes++;
  }
}


모든 것이 다소 간단합니다. 템플릿의 핸들러가 호출될 때마다 증가하는 속성이 있습니다. 상황을 보여주기 위해 rxjs' SubjectdebounceTime 와 함께 사용할 수 있지만 이러한 솔루션은 이를 구현하는 구성 요소로 제한되며 메서드 호출을 디바운싱해야 할 수 있는 다른 구성 요소로 전송할 수 없습니다.

우리가 대안으로 할 수 있는 것은 디바운스 시간(밀리초)을 받아들이고 Promise를 활용하여 메서드 실행을 연기하는 매개변수화된 데코레이터를 만드는 것입니다.

export function debounce(ms: number) {
  return (
    target: unknown,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ): void => {
    let timer: ReturnType<typeof setTimeout>;
    const originalMethod = descriptor.value;

    descriptor.value = function (...args: any[]) {
      new Promise((resolve) => {
        if (timer) {
          clearTimeout(timer);
        }

        timer = setTimeout(() => {
          resolve(originalMethod.apply(this, ...args));
        }, ms);
      });
    };
  };
}


이 접근 방식의 멋진 점은 이제 모든 구성 요소의 모든 메서드에 적용할 수 있는 별도의 디바운싱 메커니즘이 있다는 것입니다. 따라서 증분을 2초로 제한하려면 메서드를 간단하게 꾸밀 수 있습니다.

import { Component } from '@angular/core';

import { debounce } from './debounce/debounce.decorator';

@Component({
  template: `<p>{{ calledTimes }}</p>
    <p><button (click)="increment()">increment</button></p>`,
  selector: 'app-root',
})
export class AppComponent {
  private _calledTimes = 0;

  public get calledTimes(): number {
    return this._calledTimes;
  }

  @debounce(2000)
  public increment(): void {
    this._calledTimes++;
  }
}


간단합니다 :)

좋은 웹페이지 즐겨찾기