Cómo crear un temporizador en angular2

95

Necesito un temporizador en Angular 2, que marca después de un intervalo de tiempo y realiza alguna tarea (puede ser llamar a algunas funciones).

¿Cómo hacer esto con Angular 2?

kuntal
fuente
2
Incluya solo el código suficiente para permitir que otros reproduzcan el problema. Para obtener ayuda con esto, lea Cómo crear un ejemplo mínimo, completo y verificable. Si es posible crear un ejemplo en vivo del problema al que puede vincular (por ejemplo, en sqlfiddle.com o jsbin.com ), hágalo, pero también incluya el código en su pregunta. No todo el mundo puede acceder a sitios externos y los enlaces pueden romperse con el tiempo.
Prasad
15
En realidad, esta es una pregunta muy útil. Los observables son importantes para aprender y usar. Incluso si el usuario no tiene un código para partir de esta pregunta, será útil para otros.
Winnemucca
Este comentario cae en el mismo cubo, pero ninguna de las 2 personas anteriores ha ayudado, solo comentó la pregunta ... Aparentemente, la gente está usando setTimeout nuevamente ahora.
rbnzdave
setTimeout es realmente de la vieja escuela - echa un vistazo al nuevo TimerObservable a continuación
Philip
2
let this._timer = setInterval (() => this.getWidgetData (), 10000); y asegúrese de llamar a clearInterval (this._timer); al destruir
crh225

Respuestas:

129

Además de todas las respuestas anteriores, lo haría usando RxJS Observables

por favor revise Observable.timer

Aquí hay un código de muestra, comenzará después de 2 segundos y luego marcará cada segundo:

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

Y aquí hay un plunker que funciona

Actualizar Si desea llamar a una función declarada en la clase AppComponent, puede realizar una de las siguientes acciones:

** Suponiendo que la función que desea llamar se llama func ,

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

El problema con el enfoque anterior es que si llama a 'esto' dentro de la función, se referirá al objeto del suscriptor en lugar del objeto AppComponent, que probablemente no sea lo que desea.

Sin embargo, en el siguiente enfoque, crea una expresión lambda y llama a la función func dentro de ella. De esta manera, la llamada a func todavía está dentro del alcance de AppComponent. Esta es la mejor forma de hacerlo en mi opinión.

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

revise este plunker para ver el código de trabajo.

Abdulrahman Alsoghayer
fuente
¿Debería poder pasar una función a `timer.subscribe (t => this.ticks = t);` que es una llamada en cada tick?
kuntal
@matrixwebtech Sí, 't => this.ticks = t' es una expresión lambda, exactamente lo mismo que 'function (t) {this.ticks = t}'
Abdulrahman Alsoghayer
Intento timer.subscribe (function name () {console.log ("hhhhhh")}); cuál funciona pero cómo llamo a una función que declaró por separado ngOnInit () {let timer = Observable.timer (2000,1000); timer.subscribe (function () {this.fun ();}); } fun () {console.log ("hhhhhh")}
kuntal
@matrixwebtech, consulte mi respuesta actualizada para ver ejemplos.
Abdulrahman Alsoghayer
1
@Notflip Debajo del capó, timerparece usar setInterval(). Pero, puede pasar el animationFrameprogramador (que usa requestAnimationFrame()) para usarlo en lugar del asyncprogramador predeterminado . Todo lo que necesita hacer es Observable.timer(*,*,Scheduler.animationFrame), dado. import {Scheduler} from ‘rxjs’Aunque, timerno parece funcionar. Todavía parece usar setInterVal(). Sin embargo, en otros tipos de observables como Observable.range(0,1000,Scheduler.animationFrame), el requestAnimationFramese usa con seguridad. En cuanto al rendimiento, no puedo responderte con seguridad en este momento.
Abdulrahman Alsoghayer
79

Otra solución es utilizar TimerObservable

TimerObservable es una subclase 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();
  }
}

PD: No te olvides de darte de baja.

Felipe
fuente
3
la parte para cancelar la suscripción es clave
Tucker
¿cómo se da de baja? ¿y cuando?
Miguel Stevens
1
Se llama a @Notflip ngOnDestroy durante la desinicialización del componente: cancela la this.subscription.unsubscribe();suscripción.
Philip
¿Cómo puede utilizar this.subscription sin hacer referencia a ella arriba?
Winnemucca
2
¿Cómo pausarlo y reiniciarlo?
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
fuente
3
Esto no agrega nada que no se haya explicado en otras respuestas, ¿o sí?
Günter Zöchbauer
5

Con rxjs 6.2.2 y Angular 6.1.7, obtenía un:

Observable.timer is not a function

error. Esto se resolvió reemplazando Observable.timercon 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
fuente
3
Para cancelar la suscripción, debe tener una variable de suscripción como @ alexis-poo arriba. Ver: stackoverflow.com/questions/40181169/… . Baso esto en que su respuesta no funciona como está escrita en ese sentido.
Reid
Amo a este tipo que siempre está actualizando las publicaciones a las versiones más nuevas de Angular ... Cada vez hay tanta lucha con AngularJS y Angular. ¡Gracias hombre!
escalera
4

Simplemente puede usar la utilidad setInterval y usar la función de flecha como devolución de llamada para que thisapunte a la instancia del componente.

Por ejemplo:

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

Dentro de su gancho de ciclo de vida ngOnDestroy, borre el intervalo.

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

Me enfrenté al problema de que tenía que usar un temporizador, pero tenía que mostrarlos en 2 componentes al mismo tiempo, la misma pantalla. Creé el timerObservable en un servicio. Me suscribí al temporizador en ambos componentes y ¿qué sucedió? No se sincronizará, porque la nueva suscripción siempre crea su propia transmisión.

Lo que me gustaría decir es que si planeas usar un temporizador en varios lugares, colócalo siempre .publishReplay(1).refCount() al final del Observador, porque publicará la misma secuencia cada vez.

Ejemplo:

this.startDateTimer = Observable.combineLatest(this.timer, this.startDate$, (localTimer, startDate) => {
  return this.calculateTime(startDate);
}).publishReplay(1).refCount();
xyztdanid4
fuente
¿Puedes compartir tu implementación?
Nitish Kumar
1

Encontré un paquete npm que lo hace fácil con RxJS como servicio.

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

Puede 'suscribirse' a un temporizador existente para no crear un billón de temporizadores si lo usa muchas veces en el mismo componente.

Simon_Weaver
fuente
1

Si busca ejecutar un método en ngOnInit, podría hacer algo como esto:

importar estas 2 bibliotecas de RXJS:

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

Luego declare el temporizador y la suscripción privada, ejemplo:

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

Por último, pero no menos importante, ejecutar el método cuando el temporizador se detiene

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

Eso es todo, Angular 5

Alexis Poo
fuente
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
fuente