99

I need a timer in Angular 2, which tick after a time interval and do some task (may be call some functions).

How to do this with Angular 2?

5
  • 2
    Include just enough code to allow others to reproduce the problem. For help with this, read How to create a Minimal, Complete, and Verifiable example. If it is possible to create a live example of the problem that you can link to (for example, on sqlfiddle.com or jsbin.com) then do so - but also include the code in your question itself. Not everyone can access external sites, and the links may break over time. Commented Mar 5, 2016 at 11:10
  • 16
    This is actually a very helpful question. Observables are important to learn and use. Even if the user didn't have code to go from this question will be helpful to others. Commented Apr 12, 2016 at 16:36
  • This comment falls in the same bucket, but neither of the previous 2 people have helped, just commented on the question... Apparently people are using setTimeout again now. Commented Aug 1, 2016 at 19:09
  • setTimeout is really old-school - checkout out the fresh TimerObservable below Commented Sep 23, 2016 at 15:50
  • 2
    let this._timer = setInterval(() => this.getWidgetData(), 10000); and make sure to call clearInterval(this._timer); on destroy Commented Nov 9, 2016 at 18:36

10 Answers 10

129

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.

Sign up to request clarification or add additional context in comments.

14 Comments

Should I able to pass a function to ` timer.subscribe(t=>this.ticks = t);` which is call in every tick ?
@matrixwebtech Yes, the 't=>this.ticks = t' is a lambda expression, exactly the same as 'function(t){ this.ticks = t }'
I try timer.subscribe(function name() { console.log("hhhhhh") }); which working but how I call a function which declared separately ngOnInit() { let timer = Observable.timer(2000,1000); timer.subscribe(function() { this.fun(); }); } fun() { console.log("hhhhhh") }
@matrixwebtech please check my updated answer for examples.
@Notflip Under the hood, timer seems to use setInterval(). But, you can pass the animationFrame scheduler (which uses requestAnimationFrame()) to use it instead of the default async scheduler. All you need to do is Observable.timer(*,*,Scheduler.animationFrame), given import {Scheduler} from ‘rxjs’.Although, on timer it doesn't seem to work. It still seems to use setInterVal(). However, on other kinds of observable such as Observable.range(0,1000,Scheduler.animationFrame), the requestAnimationFrame is used for sure. performance wise, I can't answer you for sure right now.
|
79

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.

7 Comments

the unsubscribe part is key
how do you unsubscribe? and when?
@Notflip ngOnDestroy is called during component deinitialization: this.subscription.unsubscribe(); unsubscribes.
How are you able to use this.subscription without referencing it above?
How do you pause and restart it?
|
12
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();

    }


}

1 Comment

This doesn't add anything that isn't already explained in other answers, or does it?
8

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();    
}

2 Comments

To do the unsubscribe, you have to have a subscription variable like @alexis-poo above. See: stackoverflow.com/questions/40181169/…. I base this on your answer not working as written in that regard.
I love this guy who is always updating the Posts to the newest Angular versions... Everytime so much struggle with AngularJS and Angular. Thanks man!
4

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);
}

Comments

3

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();

1 Comment

can you share you implementation ?
1

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.

Comments

1

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

Comments

0

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 => { },
        );
    }

Comments

0

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);
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.