Reputation: 320
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
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