Fbx is loading but animate function is going to infinite loop - Angular 8

Hi, i’m using Angular 8 and when I try to go back previous url or click in another link my web is in infinite loop with animate function, this is my code, and i don’t know can i how to do it well to exit of this infinite loop, I have this problem with all objects that I can try, normally I try with mixamo fbx with skin:

import { Component, ElementRef, Input, OnDestroy, ViewChild } from '@angular/core';
import { Select } from '@ngxs/store';
import { Observable } from 'rxjs';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import { FBXLoader } from 'three/examples/jsm/loaders/FBXLoader.js';
import { environment } from '../../../../environments/environment';
import { Movement } from '../../movements/classes/movement';

@Component({
  selector: 'app-three',
  templateUrl: './three.component.html',
  styleUrls: ['./three.component.scss'],
})
export class ThreeComponent implements OnDestroy {
  @Select((state) => state.visor.selected_movement) movement$: Observable<Movement>;

  @ViewChild('rendererContainer', { static: false })
  rendererContainer!: ElementRef;
  @Input() darkMode: boolean;

  environment = `${environment.publicAssetsUrl}`;

  loaderType: string | undefined;

  nativeElement: any;
  comp: any;
  object: any;

  // OBJECT
  object3D: any;

  renderer: any;
  camera: any;
  scene: any;
  controls: any;
  mixer: any;
  clock = new THREE.Clock();
  action: any;

  //
  threeDPath: string;
  requestId;
  //
  movement: Movement;
  constructor(el: ElementRef) {
    this.movement$.subscribe((movement) => {
      if (movement) {
        this.movement = movement;
        this.threeDPath = this.environment + movement.urlMovement;
        console.log('Movimiento ->', movement);
        console.log('Movimiento Path ->', this.threeDPath);
      }
    });

    this.nativeElement = el.nativeElement;
    setTimeout(() => {
      this.loaderType = this.threeDPath.substr(this.threeDPath.lastIndexOf('.') + 1);
      this.play3D();
      this.onWindowResize();
      this.animate();
    });
    this.render = this.render.bind(this);
    this.onWindowResize = this.onWindowResize.bind(this);
    this.onProgress = this.onProgress.bind(this);
    this.animate = this.animate.bind(this);
  }

  ngOnDestroy() {
    console.log('DESTROY');
    this.renderer.dispose();
    cancelAnimationFrame(this.requestId);
  }

  animate() {
    console.log('Animate');
    this.requestId = requestAnimationFrame(this.animate);

    const delta = this.clock.getDelta();

    if (this.mixer) {
      this.mixer.update(delta);
    }

    this.controls.update();

    this.render();
  }

  play3D() {
    const domElement = this.nativeElement.children[0];
    domElement.innerHTML = '';
    this.renderer = new THREE.WebGLRenderer({
      antialias: true,
      preserveDrawingBuffer: true,
    });
    this.renderer.setPixelRatio(window.devicePixelRatio);
    this.renderer.shadowMap.enabled = true;
    this.renderer.setSize(domElement.offsetWidth, domElement.offsetHeight);

    domElement.appendChild(this.renderer.domElement);

    this.clock = new THREE.Clock();

    // create scene
    this.scene = new THREE.Scene();
    this.scene.background = new THREE.Color(0x000000);
   

    // add camera
    this.scene.add(new THREE.AmbientLight(0xcccccc, 0.4));
    this.camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);
    this.camera.add(new THREE.PointLight(0xffffff, 0.8));

    this.scene.add(this.camera);

    // add light
    const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
    hemiLight.position.set(0, 20, 0);
    this.scene.add(hemiLight);

    const dirLight = new THREE.DirectionalLight(0xffffff);
    dirLight.position.set(-3, 10, -10);
    dirLight.castShadow = true;
    dirLight.shadow.camera.top = 2;
    dirLight.shadow.camera.bottom = -2;
    dirLight.shadow.camera.left = -2;
    dirLight.shadow.camera.right = 2;
    dirLight.shadow.camera.near = 0.1;
    dirLight.shadow.camera.far = 40;
    this.scene.add(dirLight);

    // axes
    this.scene.add(new THREE.AxesHelper(20));

    // controls
    this.controls = new OrbitControls(this.camera, this.renderer.domElement);

    // ground
    const mesh = new THREE.Mesh(
      new THREE.PlaneBufferGeometry(2000, 2000),
      new THREE.MeshPhongMaterial({ color: 0xd0bb95, depthWrite: false }),
    );
    mesh.rotation.x = -Math.PI / 2;
    mesh.receiveShadow = true;
    this.scene.add(mesh);

    const grid = new THREE.GridHelper(2000, 20, 0x000000, 0x000000);
    this.scene.add(grid);

    // loader FBX
    const loader = new FBXLoader();
    loader.load(
      this.threeDPath,
      (objLoaded: any) => {
        console.log('Object', objLoaded);
        const box = new THREE.Box3().setFromObject(objLoaded);
        const size = box.getSize(new THREE.Vector3()).length();
        const center = box.getCenter(new THREE.Vector3());
        this.controls.reset();

        // object position
        objLoaded.position.x += objLoaded.position.x - center.x;
        objLoaded.position.y += objLoaded.position.y;
        objLoaded.position.z += objLoaded.position.z - center.z;
        this.controls.maxDistance = size * 10;

        // camera position respect object
        this.camera.near = size / 100;
        this.camera.far = size * 100;
        this.camera.updateProjectionMatrix();

        this.camera.position.copy(center);
        this.camera.position.x -= size;
        this.camera.position.y += size / 4;
        this.camera.position.z += size;

        this.camera.lookAt(center);

        objLoaded.traverse((object: { isMesh: any; castShadow: boolean }) => {
          if (object.isMesh) {
            object.castShadow = true;
          }
        });

        // animation
        // Create an AnimationMixer, and get the list of AnimationClip instances
        this.mixer = new THREE.AnimationMixer(objLoaded);
        this.action = this.mixer.clipAction(objLoaded.animations[0]);
        console.log('ACTION LOAD', this.action);

        // Play a specific animation
        this.action.play();

        objLoaded.traverse((child: any) => {
          if (child.isMesh) {
            child.castShadow = true;
            child.receiveShadow = true;
          }
        });

        this.object3D = objLoaded;
        this.scene.add(this.object3D);

        this.controls.update();
        this.onWindowResize();
      },
      this.onProgress,
    );

    window.addEventListener('resize', this.onWindowResize, false);
  }

  onProgress(xhr: any) {
    if (xhr.lengthComputable) {
      const percentComplete = (xhr.loaded / xhr.total) * 100;
      console.log('model ' + percentComplete + '% downloaded');
    }
  }

  onWindowResize() {
    const domElement = this.nativeElement.children[0];
    this.camera.aspect = domElement.offsetWidth / domElement.offsetHeight;
    this.camera.updateProjectionMatrix();
    this.renderer.setSize(window.innerWidth * 0.8, window.innerHeight * 0.8);
  }

  render() {
    this.renderer.render(this.scene, this.camera);
  }
}

By “infinite loop” - you mean exceeded call stack, or just app not navigating / loading properly?

The web crashes due to the infinite load of animate() calls, and I don’t know how to stop it to be able to navigate, I thought that the ngOnDestroy would be enough.