1

I am trying to implement a method, where a angular material tab change happens after a fixed time interval. I tried using setInterval in JavaScript, but it doesnt work very reliable (the tab change occurs randomly). The code posted below works, but after some hours the browser freezes and the console shows this error:

ERROR RangeError: Maximum call stack size exceeded

togglePlay(): void {
    this.isAnimationPlaying = !this.isAnimationPlaying;
    if (this.isAnimationPlaying) {
        this.setIndex();
    } else {
        clearTimeout();
    }
}

setIndex() {
    this.selectedIndex = (this.selectedIndex + 1) % this.matTabLength;
    this.changeDetectorRef.detectChanges();
    if (this.isAnimationPlaying) {
        setTimeout(this.setIndex.bind(this), this.transitionSpeed);
    } else {
        clearTimeout();
    }
}

I tried passing the transitionSpeed in the setTimeout method like this:

setTimeout(this.setIndex, this.transitionSpeed, this.transitionSpeed);

setIndex(transitionSpeed: number, selectedIndex: number, matTabLength: number) {
    this.selectedIndex = (selectedIndex + 1) %.matTabLength;
    if (this.isAnimationPlaying) {
        setTimeout(this.setIndex, transitionSpeed, selectedIndex, matTabLength);
    } else {
        clearTimeout();
    }
}

But if the method is called a second time, this.transitionSpeed is null.

Any help is highly appreciated

EDIT:

Changed code to this but still getting the same error after some hours:

togglePlay(): void {
    this.isAnimationPlaying = !this.isAnimationPlaying;
    if (this.isAnimationPlaying) {
        this.setIndex();
    } else {
        clearTimeout(this.timerId);
    }
}

setIndex() {
    this.selectedIndex = (this.selectedIndex + 1) % this.matTabLength;
    this.changeDetectorRef.detectChanges();
    if (this.isAnimationPlaying) {
        clearTimeout(this.timerId);
        this.timerId = setTimeout(this.setIndex.bind(this), this.transitionSpeed);
    } else {
        clearTimeout(this.timerId);
    }
}

EDIT2: While changing the Tab a TabChange event is called. Code:

    tabChanged(event) {
        this.themeClassesToRemove = Array.from(this.overlayContainer.getContainerElement().classList).filter((item: string) => item.includes('-template'));
        if (Array.from(this.overlayContainer.getContainerElement().classList).filter((item: string) => item.includes('-template')).length) {
            this.overlayContainer.getContainerElement().classList.remove(...this.themeClassesToRemove);
        }
        const label = event.tab.textLabel;
        if (label.toLocaleLowerCase() === '1') {
            this.templateService.default_template = this.templateService.grey_template;
        } else if (label.toLocaleLowerCase() === '2') {
            this.templateService.default_template = this.templateService.green_template;
        } else if (label.toLocaleLowerCase() === '3') {
            this.templateService.default_template = this.templateService.red_template;
        } else {
            this.templateService.default_template = this.templateService.blue_template;
        }
        this.overlayContainer.getContainerElement().classList.add(this.templateService.default_template);
        window.dispatchEvent(new Event('resize'));
    }

This is the only method, which is called beside the timeout. According to this post, there must be recirsive method which is called all the time.

Key3en
  • 31
  • 2
  • Possible duplicate of [Maximum call stack size exceeded error](https://stackoverflow.com/questions/6095530/maximum-call-stack-size-exceeded-error) – dota2pro Jul 16 '19 at 19:41

1 Answers1

0

setTimeout. returns a timer id, which you then use in clearTimeout to clear it out:

timerId = setTimeout(this.setIndex.bind(this), this.transitionSpeed);      

clearTimeout(timerId);
Austin Greco
  • 32,997
  • 6
  • 55
  • 59
  • I tried this one and after some hours I still get the same error. Code changed are in my Edit – Key3en Jul 17 '19 at 09:10