Search code examples
angulartypescriptrxjs

Angular: Rxjs repeat() causes app to freeze


I already have some experience in Angular, but I am rather new to Rxjs. Recently I wanted to create a personal website and for that I found a Typwriter tutorial online that I wanted to recreat. It pretty much just takes an array of string and types those string after each other, so it looks like somebody is tpying.

Everything works as intended but I ran into one problem. I want to make this typing-animation indefinetly. Therefore ist just want to use the reapeat() pipe to retrigger the observable after it is finished. The more often I want to repeat it, the longer the Angular App needs to compile. When I want to repeat it indefinetly with repeat(), it just loads forever. I could really need some help with that.

Here ist the Code:

TypeWriter Service:

export class TypewriterService {
  constructor() { }

  private type({ word, speed, backwards = false }: TypeParams) {
    return interval(speed).pipe(
      map(x =>
        backwards
          ? word.substring(0, word.length - x - 1) + '_'
          : word.substring(0, x + 1) + '_'
      ),
      take(word.length)
    );
  }

  typeEffect(word: string) {
    return concat(
      this.type({ word, speed: 50 }),
      of('').pipe(delay(1200), ignoreElements()),
      this.type({ word, speed: 30, backwards: true }),
      of('').pipe(delay(300), ignoreElements())
    );
  }

  getTypewriterEffect(titles: string[]) {
    return from(titles).pipe(
      concatMap((title) => this.typeEffect(title)),
      delay(1),
      repeat()
    );

  }
}

Create a new Observable:

this.typewriterString$ = this.typeWriterService
      .getTypewriterEffect(["Software Developer", "Adventurer", "Curious Mind"])

Subscribe in template:

<h3 style="min-height: 34px;">A passionate <span class="color-primary">{{typewriterString$ | async}}</span></h3>

I tried subscribing in different ways and debugging the typewriter. This way I pinned the repeat() statement down as the problem.


Solution

  • I believe you are using ssr and that is why app is "compiled" for so long. In reality it does not compile, but it is waiting for your logic to complete and the app to become stable.

    to fix that I propose to only execute the effect on the browser, and render just the first word on server

     getTypewriterEffect(titles: string[]) {
        if(isPlatformServer(this.platformId)) {
           return of(titles[0]);
        }
        return from(titles).pipe(
          concatMap((title) => this.typeEffect(title)),
          delay(1),
          repeat()
        );
    
      }