sameer
sameer

Reputation: 320

Angular 2 same component multiple times is executing 1 by 1

Created a component named running-number.componet.ts,

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'running-number',
  templateUrl: './running-number.component.html',
  styleUrls: ['./running-number.component.css']
})
export class RunningNumberComponent implements OnInit {

  private currentValue:number = 0;

  constructor() { }

  @Input() numberForRunning:number;

  ngOnInit() {
      let obj = this;
      for (let i = 1; i <= obj.numberForRunning; i++ ) {
          setTimeout(() => {
              this.currentValue = this.currentValue + 1;
          }, 100);
      }
  }

}

and called this component 4 times with different numberForRunning input values.

<running-number numberForRunning="15645"></running-number>
<running-number numberForRunning="3543"></running-number>
<running-number numberForRunning="414"></running-number>
<running-number numberForRunning="987"></running-number>

Issues is once numberForRunning="15645" is completely done. then only numberForRunning="3543" is started. i want all the 4 components should run simultaneously. Please help me for fixing this issue.

Thanks in advance.

Upvotes: 0

Views: 2951

Answers (1)

Aluan Haddad
Aluan Haddad

Reputation: 31873

What is happening here is that, as each component is initialized, its initializer is run synchronously until it finishes. While we are indeed queuing up changes that can be interleaved by calling setTimeout, and I believe interleaving is what you are after behavior-wise, it is actually happening synchronously. Each component instance is actually synchronously creating numberForRunning timeouts, immediately before any other component's initializer is executed. This actually chokes up the event loop making the results difficult to observe.

We actually can achieve the interleaved updates by leveraging Promises. In the following example we leverage Promises, along with async/await in order to make each iteration within the init loop of some component depend on (literally await) the previous iteration.

import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'running-number',
  template: '<div>{{currentValue}}</div>'
})
export class RunningNumberComponent implements OnInit {

  private currentValue = 0;

  @Input() numberForRunning: number;

  @Input() rateOfChange = 1;

  async ngOnInit() {
    const period = 1000 * this.rateOfChange;
    for (let i = 1; i <= this.numberForRunning; i++) {
      await delay(period);
      this.currentValue = this.currentValue + 1;
    }
  }

}

function delay(ms) {
  return new Promise(resolve => setTimeout(() => resolve(undefined), ms));
}

Here it is, running, https://plnkr.co/edit/9bnwr4wNQPbIergDTq1n?p=preview

This works because it means that the initializers actually return Promises which in turn beget more Promises. Instead of performing their work synchronously it is interleaved. So initialization and the subsequent operations that happen over time as a result of the process thusly started actually gets interleaved. The rateOfChange property is introduced to allow us to see this happening more easily.

I apologize as this is somewhat hand-waving but I hope it gets at the underlying issues and provides a high level illustration.

Upvotes: 1

Related Questions