Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Event handler performance issue in Angular 4 / 5

Tags:

Sorry if my question is silly, but we are facing a latency issue in our application. KEYPRESS event handler is the culprit. We are using this below directive in the entire application. It checks KeyPress through HostListener. When key pressed, this directive checks the value with regexp and does preventDefault if condition is false.

private regexMap = { // add your own
    '999': /^([0-9]){0,3}$/g,
    '9999': /^([0-9]){0,4}$/g,
    ...
    ...
}

@HostListener('keypress', [ '$event' ])
public nInput(event: KeyboardEvent) {
    // Allow Backspace, tab, end, and home keys
    if (this.specialKeys.indexOf(event.key) !== -1) {
        return;
    }
    this.pattern = this.regexMap[this.validationFormat];
    const current: string = this.el.nativeElement.value;
    const next: string = current.concat(event.key);
    if (next && !String(next).match(this.pattern)) {
        event.preventDefault();
    }
}

I am not sure how to fix this issue. Will debounceTime fix this issue? I am not sure how to add debounce to this method. Please someone help me to solve this issue.

like image 804
Munna Babu Avatar asked Mar 02 '18 08:03

Munna Babu


2 Answers

Fixed issue with DebounceTime :) just added debounce time with help Subject. Basically when user enter something it stop all action, then send EVENT(key pressed value) to SUBJECT and In subject debounce Time wait 300ms and then do function test

    private keyPressed = new Subject();
    private subscription: Subscription;
    private pattern: RegExp;
    private regexMap = { // add your own
     '999': /^([0-9]){0,3}$/g,
     '9999': /^([0-9]){0,4}$/g,
      ...
      ...
   }
    private specialKeys: string[] = ['Backspace', 'Tab', 'End', 'Home'];

    constructor(private el: ElementRef) {
    }

    public ngOnInit() {
        this.subscription = this.keyPressed.pipe(debounceTime(300)).subscribe(
            (event) => this.checkRegExpression(event)
        );
    }

    public ngOnDestroy() {
        this.subscription.unsubscribe();
    }

    @HostListener('keypress', ['$event']) public nInput(event: KeyboardEvent) {
        event.preventDefault();
        event.stopPropagation();
        this.keyPressed.next(event);
    }

    private checkRegExpression(event) {
        if (this.specialKeys.indexOf(event.key) !== -1) {
            return;
        }
        this.pattern = this.regexMap[this.validationFormat];
        const current: string = this.el.nativeElement.value;
        const next: string = current.concat(event.key);
        if (next && !String(next).match(this.pattern)) {
            event.preventDefault();
        }
    }
like image 85
Munna Babu Avatar answered Sep 20 '22 11:09

Munna Babu


Assuming that you want to keep using keypress events, which fires for every keypress by user

Try optimizing the Regex:

i.e remove g and brackets from regex. Make the regex like this -

/^[0-9]{0,3}$/

For more tricks refer: Regex Optimizations

Websites are particularly bad with Streaming Validation (i.e. Validating text, live!)

  1. If it is okay to not have a streaming validation check, then use focus lost event, i.e. run your code after focus is lost from text field.
  2. Or better yet, do it like Angular documentation suggests Email Validation Demo, don't correct the mistakes, just point it out, user will correct it.
like image 20
Abhijit Kar ツ Avatar answered Sep 24 '22 11:09

Abhijit Kar ツ