Comment créer une minuterie dans angular2

95

J'ai besoin d'une minuterie dans Angular 2, qui coche après un intervalle de temps et effectue une tâche (peut-être appeler certaines fonctions).

Comment faire cela avec Angular 2?

Kuntal
la source
2
Incluez juste assez de code pour permettre aux autres de reproduire le problème. Pour obtenir de l'aide, lisez Comment créer un exemple minimal, complet et vérifiable. S'il est possible de créer un exemple en direct du problème auquel vous pouvez créer un lien (par exemple, sur sqlfiddle.com ou jsbin.com ), faites-le - mais incluez également le code dans votre question elle-même. Tout le monde ne peut pas accéder à des sites externes et les liens peuvent se rompre avec le temps.
Prasad
15
C'est en fait une question très utile. Les observables sont importants à apprendre et à utiliser. Même si l'utilisateur n'a pas de code pour passer, cette question sera utile aux autres.
Winnemucca
Ce commentaire tombe dans le même seau, mais aucune des 2 personnes précédentes n'a aidé, vient de commenter la question ... Apparemment, les gens utilisent à nouveau setTimeout maintenant.
rbnzdave
setTimeout est vraiment old-school - consultez le nouveau TimerObservable ci
Philip
2
laissez this._timer = setInterval (() => this.getWidgetData (), 10000); et assurez-vous d'appeler clearInterval (this._timer); sur destroy
crh225

Réponses:

129

En plus de toutes les réponses précédentes, je le ferais en utilisant les observables RxJS

veuillez vérifier Observable.timer

Voici un exemple de code, démarrera après 2 secondes, puis cochera toutes les secondes:

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

Et voici un plunker de travail

Mettre à jour Si vous souhaitez appeler une fonction déclarée sur la classe AppComponent, vous pouvez effectuer l'une des opérations suivantes:

** En supposant que la fonction que vous souhaitez appeler s'appelle func ,

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

Le problème avec l'approche ci-dessus est que si vous appelez 'this' à l'intérieur de func, il se référera à l'objet abonné au lieu de l'objet AppComponent, ce qui n'est probablement pas ce que vous voulez.

Cependant, dans l'approche ci-dessous, vous créez une expression lambda et appelez la fonction func à l' intérieur. De cette façon, l'appel à func est toujours dans la portée d'AppComponent. C'est la meilleure façon de le faire à mon avis.

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

vérifiez ce plunker pour le code de travail.

Abdulrahman Alsoghayer
la source
Dois-je pouvoir passer une fonction à `timer.subscribe (t => this.ticks = t);` qui est un appel à chaque tick?
kuntal
@matrixwebtech Oui, le 't => this.ticks = t' est une expression lambda, exactement la même chose que 'function (t) {this.ticks = t}'
Abdulrahman Alsoghayer
J'essaye timer.subscribe (function name () {console.log ("hhhhhh")}); qui fonctionne mais comment j'appelle une fonction qui a déclaré séparément ngOnInit () {let timer = Observable.timer (2000,1000); timer.subscribe (function () {this.fun ();}); } fun () {console.log ("hhhhhh")}
kuntal
@matrixwebtech s'il vous plaît vérifier ma réponse mise à jour pour des exemples.
Abdulrahman Alsoghayer
1
@Notflip Sous le capot, timersemble utiliser setInterval(). Mais, vous pouvez passer le animationFrameplanificateur (qui utilise requestAnimationFrame()) pour l'utiliser à la place du asyncplanificateur par défaut . Tout ce que vous avez à faire est Observable.timer(*,*,Scheduler.animationFrame), étant donné. import {Scheduler} from ‘rxjs’Bien que timercela ne semble pas fonctionner. Il semble toujours utiliser setInterVal(). Cependant, sur d'autres types d'observables tels que Observable.range(0,1000,Scheduler.animationFrame), le requestAnimationFrameest utilisé à coup sûr. en termes de performances, je ne peux pas vous répondre avec certitude pour le moment.
Abdulrahman Alsoghayer
79

Une autre solution consiste à utiliser TimerObservable

TimerObservable est une sous-classe de 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();
  }
}

PS: N'oubliez pas de vous désabonner.

Philippe
la source
3
la partie de désabonnement est la clé
Tucker
comment vous désinscrire? et quand?
Miguel Stevens
1
@Notflip ngOnDestroy est appelé lors de la désinitialisation du composant: se this.subscription.unsubscribe();désabonne.
Philip
Comment pouvez-vous utiliser this.subscription sans le référencer ci-dessus?
Winnemucca
2
Comment le suspendre et le redémarrer?
Dani
11
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();

    }


}
Unnikrishnan Parameswaran
la source
3
Cela n'ajoute rien qui n'est pas déjà expliqué dans d'autres réponses, ou est-ce le cas?
Günter Zöchbauer
5

Avec rxjs 6.2.2 et Angular 6.1.7, j'obtenais un:

Observable.timer is not a function

Erreur. Ce problème a été résolu en remplaçant Observable.timerpar 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();    
}
Matt Saunders
la source
3
Pour faire le désabonnement, vous devez avoir une variable d'abonnement comme @ alexis-poo ci-dessus. Voir: stackoverflow.com/questions/40181169/… . Je fonde cela sur votre réponse qui ne fonctionne pas comme écrit à cet égard.
Reid
J'adore ce gars qui met toujours à jour les messages vers les dernières versions Angular ... À chaque fois, tant de difficultés avec AngularJS et Angular. Merci mec!
escalier de
4

Vous pouvez simplement utiliser l'utilitaire setInterval et utiliser la fonction de flèche comme rappel pour thispointer vers l'instance du composant.

Par exemple:

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

Dans votre hook de cycle de vie ngOnDestroy, effacez l'intervalle.

ngOnDestroy(){
    clearInterval(this.interval);
}
Shivang Gupta
la source
3

J'ai rencontré un problème que je devais utiliser une minuterie, mais je devais les afficher en 2 composants en même temps, même écran. J'ai créé le timerObservable dans un service. Je me suis abonné au minuteur dans les deux composants et que s'est-il passé? Il ne sera pas synchronisé, car le nouvel abonnement crée toujours son propre flux.

Ce que je voudrais dire, c'est que si vous prévoyez d'utiliser une minuterie à plusieurs endroits, toujours placée .publishReplay(1).refCount() à la fin de l'Observer, car il publiera le même flux à chaque fois.

Exemple:

this.startDateTimer = Observable.combineLatest(this.timer, this.startDate$, (localTimer, startDate) => {
  return this.calculateTime(startDate);
}).publishReplay(1).refCount();
xyztdanid4
la source
pouvez-vous partager votre mise en œuvre?
Nitish Kumar
1

Nous avons trouvé un package npm qui rend cela facile avec RxJS en tant que service.

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

Vous pouvez vous «abonner» à un minuteur existant pour ne pas créer un bazillion de minuteries si vous l'utilisez plusieurs fois dans le même composant.

Simon_Weaver
la source
1

Si vous cherchez à exécuter une méthode sur ngOnInit, vous pouvez faire quelque chose comme ceci:

importez ces 2 bibliothèques depuis RXJS:

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

Ensuite, déclarez le minuteur et l'abonnement privé, exemple:

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

Dernière mais non la moindre méthode d'exécution lorsque la minuterie s'arrête

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

C'est tout, Angular 5

Alexis Poo
la source
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 => { },
    );
}
Nazmul Nadim
la source