如何在angular2中创建计时器


95

我需要在Angular 2中使用一个计时器,该计时器会在一个时间间隔后滴答作响,并执行某些任务(可能会调用某些函数)。

如何使用Angular 2做到这一点?


2
仅包含足够的代码,以允许其他人重现该问题。有关此方面的帮助,请阅读如何创建最小,完整和可验证的示例。如果可以创建您可以链接到的问题的实时示例(例如,在sqlfiddle.comjsbin.com上),则可以这样做-并在问题本身中包含代码。并非所有人都可以访问外部站点,并且链接可能会随着时间而中断。
普拉萨德

15
这实际上是一个非常有用的问题。观测资料对于学习和使用非常重要。即使用户没有代码可以解决这个问题,对其他人也会有所帮助。
Winnemucca

此评论属于同一组,但前两个人都没有帮助,只是评论了这个问题……显然,人们现在又在使用setTimeout。
rbnzdave '16

setTimeout确实很老套-请在下面
Philip

2
让this._timer = setInterval(()=> this.getWidgetData(),10000); 并确保调用clearInterval(this._timer); 毁灭时
crh225 '16

Answers:


129

除了上述所有答案外,我还将使用RxJS Observables进行此操作

请检查Observable.timer

这是一个示例代码,将在2秒后开始,然后每秒滴答一次:

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

这是一个工作的家伙

更新 如果要调用在AppComponent类上声明的函数,则可以执行以下任一操作:

**假设您要调用的函数名为func

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

上面方法的问题是,如果在func内部调用“ this”,它将引用订户对象而不是AppComponent对象,而这可能不是您想要的。

但是,在下面的方法中,您将创建一个lambda表达式并在其中调用函数func。这样,对func的调用仍然在AppComponent的范围之内。我认为这是最好的方法。

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

检查此插件的工作代码。


我是否应该能够将函数传递给在每个刻度中调用的timer.subscribe(t => this.ticks = t);?
肯塔尔

@matrixwebtech是的,'t => this.ticks = t'是lambda表达式,与'function(t){this.ticks = t}'
完全相同

我尝试使用timer.subscribe(function name(){console.log(“ hhhhhh”)}); 哪个工作,但我如何调用分别声明ngOnInit()的函数{let timer = Observable.timer(2000,1000); timer.subscribe(function(){this.fun();}); } fun(){console.log(“ hhhhhh”)}
2016年

@matrixwebtech请查看我更新的答案以获取示例。
Abdulrahman Alsoghayer

1
@Notflip timer似乎在使用setInterval()。但是,您可以传递animationFrame调度程序(使用requestAnimationFrame())来代替默认async调度程序来使用它。Observable.timer(*,*,Scheduler.animationFrame)给定您需要做的就是import {Scheduler} from ‘rxjs’。尽管如此,timer它似乎并不起作用。它似乎仍然有用setInterVal()。然而,在其他类型的可观察到如Observable.range(0,1000,Scheduler.animationFrame),将requestAnimationFrame用于确定。在性能方面,我目前无法确定。
Abdulrahman Alsoghayer '17

79

另一个解决方案是使用TimerObservable

TimerObservable是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:别忘了取消订阅。


3
取消订阅的部分很关键
Tucker

您如何退订?什么时候?
米格尔·史蒂文斯

1
@Notflip ngOnDestroy在组件this.subscription.unsubscribe();取消初始化期间被调用:取消订阅。
菲利普(Philip)

您如何能够在不参考上面的情况下使用this.subscription?
Winnemucca

2
如何暂停并重新启动它?
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();

    }


}

3
这不会添加其他答案中尚未解释的任何内容,或者是?
君特Zöchbauer

5

使用rxjs 6.2.2和Angular 6.1.7,我得到了:

Observable.timer is not a function

错误。解决方法是替换Observable.timertimer

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

3
要取消订阅,您必须具有上面的@ alexis-poo这样的订阅变量。请参阅:stackoverflow.com/questions/40181169/…。我基于您的回答在这方面不起作用。
Reid

我喜欢这个总是将Posts更新到最新Angular版本的家伙...每次与AngularJS和Angular进行如此多的斗争。谢啦!
chainstair

4

您可以简单地使用setInterval实用程序,并使用箭头函数作为回调,以便this指向组件实例。

例如:

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

在ngOnDestroy生命周期挂钩中,清除时间间隔。

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

3

我遇到了必须使用计时器的问题,但是必须同时在两个组件中,同一屏幕上显示它们。我在服务中创建了timerObservable。我在两个组件中都订阅了计时器,发生了什么?它不会被同步,因为新的订阅总是创建自己的流。

我想说的是,如果您打算在多个位置使用一个计时器(总是放在.publishReplay(1).refCount() 观察者的末尾),因为它每次都会在其中发布相同的流。

例:

this.startDateTimer = Observable.combineLatest(this.timer, this.startDate$, (localTimer, startDate) => {
  return this.calculateTime(startDate);
}).publishReplay(1).refCount();

你能分享你的实现吗?
Nitish Kumar


1

如果希望在ngOnInit上运行方法,则可以执行以下操作:

从RXJS导入这2个库:

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

然后声明计时器和私有订阅,例如:

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

计时器停止时的最后但并非最不重要的运行方法

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

就是了,Angular 5


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 => { },
    );
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.