如何在角度2中创建计时器

我需要一个角度2的计时器,它在一个时间间隔后计时并执行一些任务(可以调用一些函数)。

如何做到这一点与角度2?

130031 次浏览

In Addition to all the previous answers, I would do it using RxJS Observables

please check Observable.timer

Here is a sample code, will start after 2 seconds and then ticks every second:

import {Component} from 'angular2/core';
import {Observable} from 'rxjs/Rx';


@Component({
selector: 'my-app',
template: 'Ticks (every second) : \{\{ticks}}'
})
export class AppComponent {
ticks =0;
ngOnInit(){
let timer = Observable.timer(2000,1000);
timer.subscribe(t=>this.ticks = t);
}
}

And here is a working plunker

Update If you want to call a function declared on the AppComponent class, you can do one of the following:

** Assuming the function you want to call is named func,

ngOnInit(){
let timer = Observable.timer(2000,1000);
timer.subscribe(this.func);
}

The problem with the above approach is that if you call 'this' inside func, it will refer to the subscriber object instead of the AppComponent object which is probably not what you want.

However, in the below approach, you create a lambda expression and call the function func inside it. This way, the call to func is still inside the scope of AppComponent. This is the best way to do it in my opinion.

ngOnInit(){
let timer = Observable.timer(2000,1000);
timer.subscribe(t=> {
this.func(t);
});
}

check this plunker for working code.

Another solution is to use TimerObservable

TimerObservable is a subclass of Observable.

import {Component, OnInit, OnDestroy} from '@angular/core';
import {Subscription} from "rxjs";
import {TimerObservable} from "rxjs/observable/TimerObservable";


@Component({
selector: 'app-component',
template: '\{\{tick}}',
})
export class Component implements OnInit, OnDestroy {


private tick: string;
private subscription: Subscription;


constructor() {
}


ngOnInit() {
let timer = TimerObservable.create(2000, 1000);
this.subscription = timer.subscribe(t => {
this.tick = t;
});
}


ngOnDestroy() {
this.subscription.unsubscribe();
}
}

P.S.: Don't forget to unsubsribe.

I faced a problem that I had to use a timer, but I had to display them in 2 component same time, same screen. I created the timerObservable in a service. I subscribed to the timer in both component, and what happened? It won't be synched, cause new subscription always creates its own stream.

What I would like to say, is that if you plan to use one timer at several places, always put .publishReplay(1).refCount() at the end of the Observer, cause it will publish the same stream out of it every time.

Example:

this.startDateTimer = Observable.combineLatest(this.timer, this.startDate$, (localTimer, startDate) => {
return this.calculateTime(startDate);
}).publishReplay(1).refCount();
import {Component, View, OnInit, OnDestroy} from "angular2/core";


import { Observable, Subscription } from 'rxjs/Rx';


@Component({


})
export class NewContactComponent implements OnInit, OnDestroy {


ticks = 0;
private timer;
// Subscription object
private sub: Subscription;




ngOnInit() {
this.timer = Observable.timer(2000,5000);
// subscribing to a observable returns a subscription object
this.sub = this.timer.subscribe(t => this.tickerFunc(t));
}
tickerFunc(tick){
console.log(this);
this.ticks = tick
}


ngOnDestroy(){
console.log("Destroy timer");
// unsubscribe here
this.sub.unsubscribe();


}




}

Found a npm package that makes this easy with RxJS as a service.

https://www.npmjs.com/package/ng2-simple-timer

You can 'subscribe' to an existing timer so you don't create a bazillion timers if you're using it many times in the same component.

You can simply use setInterval utility and use arrow function as callback so that this will point to the component instance.

For ex:

this.interval = setInterval( () => {
// call your functions like
this.getList();
this.updateInfo();
});

Inside your ngOnDestroy lifecycle hook, clear the interval.

ngOnDestroy(){
clearInterval(this.interval);
}

If you look to run a method on ngOnInit you could do something like this:

import this 2 libraries from RXJS:

import {Observable} from 'rxjs/Rx';
import {Subscription} from "rxjs";

Then declare timer and private subscription, example:

timer= Observable.timer(1000,1000); // 1 second for 2 seconds (2000,1000) etc
private subscription: Subscription;

Last but not least run method when timer stops

ngOnInit() {
this.subscription = this.timer.subscribe(ticks=> {
this.populatecombobox();  //example calling a method that populates a combobox
this.subscription.unsubscribe();  //you need to unsubscribe or it will run infinite times
});
}

That's all, Angular 5

With rxjs 6.2.2 and Angular 6.1.7, I was getting an:

Observable.timer is not a function

error. This was resolved by replacing Observable.timer with timer:

import { timer, Subscription } from 'rxjs';


private myTimerSub: Subscription;


ngOnInit(){
const ti = timer(2000,1000);
this.myTimerSub = ti.subscribe(t => {
console.log("Tick");
});
}


ngOnDestroy() {
this.myTimerSub.unsubscribe();
}

Set Timer and auto call service after certain time

 // Initialize from ngInit
ngOnInit(): void {this.getNotifications();}
    

getNotifications() {
setInterval(() => {this.getNewNotifications();
}, 60000);  // 60000 milliseconds interval
}
getNewNotifications() {
this.notifyService.getNewNotifications().subscribe(
data => { // call back },
error => { },
);
}

on the newest version of Angular (I work on 12.2.*) Observable.timer is not supported. You can use it with a bit change at @Abdulrahman Alsoghayer example.

import {Component} from '@angular/core';
import {timer} from 'rxjs';


@Component({
selector: 'my-app',
template: 'Ticks (every second) : \{\{ticks}}'
})
export class AppComponent {
ticks =0;
ngOnInit(){
let timer$ = timer(2000,1000);
timer$.subscribe(t=>this.ticks = t);
}
}