【问题标题】:How to create timer in angular2如何在angular2中创建计时器
【发布时间】:2016-06-19 04:58:09
【问题描述】:

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

如何用 Angular 2 做到这一点?

【问题讨论】:

  • 包含足够的代码以允许其他人重现该问题。如需帮助,请阅读如何创建最小、完整和可验证的示例。如果可以创建一个您可以链接到的问题的实时示例(例如,在sqlfiddle.comjsbin.com 上),那么就这样做 - 但也要在您的问题本身中包含代码。不是每个人都可以访问外部网站,而且链接可能会随着时间的推移而中断。
  • 这实际上是一个非常有用的问题。 Observables 对学习和使用很重要。即使用户没有该问题的代码,也会对其他人有所帮助。
  • 这条评论属于同一个桶,但前两个人都没有帮助,只是评论了这个问题......显然人们现在又在使用 setTimeout 了。
  • setTimeout 真的很老派 - 查看下面的新鲜 TimerObservable
  • 让 this._timer = setInterval(() => this.getWidgetData(), 10000);并确保调用 clearInterval(this._timer);销毁

标签: javascript angular


【解决方案1】:

除了之前所有的答案,我会使用 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);
  }
}

这是一个有效的plunker

更新 如果要调用在 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);
    });
}

检查this plunker 的工作代码。

【讨论】:

  • 我应该能够将一个函数传递给`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") }
  • @matrixwebtech 请查看我更新的答案以获取示例。
  • @Notflip 在后台,timer 似乎使用了setInterval()。但是,您可以通过animationFrame 调度程序(使用requestAnimationFrame())来代替默认的async 调度程序来使用它。您需要做的就是Observable.timer(*,*,Scheduler.animationFrame),给定import {Scheduler} from ‘rxjs’。尽管在timer 上它似乎不起作用。它似乎仍然使用setInterVal()。但是,在其他类型的 observable 上,例如 Observable.range(0,1000,Scheduler.animationFrame),肯定会使用 requestAnimationFrame。性能方面,我现在不能肯定地回答你。
【解决方案2】:

另一种解决方案是使用 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();
  }
}

P.S.:别忘了取消订阅。

【讨论】:

  • 退订部分是关键
  • 如何退订?什么时候?
  • @Notflip ngOnDestroy 在组件取消初始化期间被调用:this.subscription.unsubscribe(); 取消订阅。
  • 如何在不引用上面的情况下使用 this.subscription?
  • 如何暂停和重启?
【解决方案3】:
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();

    }


}

【讨论】:

  • 这不会添加其他答案中尚未解释的任何内容,或者是吗?
【解决方案4】:

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

Observable.timer is not a function

错误。通过将Observable.timer 替换为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();    
}

【讨论】:

  • 要取消订阅,您必须有一个订阅变量,如上面的@alexis-poo。请参阅:stackoverflow.com/questions/40181169/…。我基于您的回答在这方面没有按照书面规定工作。
  • 我喜欢这个总是将帖子更新到最新 Angular 版本的人……每次都在与 AngularJS 和 Angular 斗争。谢谢大佬!
【解决方案5】:

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

例如:

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

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

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

【讨论】:

    【解决方案6】:

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

    我想说的是,如果您打算在多个地方使用一个计时器,请始终输入.publishReplay(1).refCount() 在 Observer 的末尾,因为它每次都会从中发布相同的流。

    例子:

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

    【讨论】:

    • 你能分享你的实现吗?
    【解决方案7】:

    找到了一个 npm 包,它通过 RxJS 即服务轻松实现。

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

    您可以“订阅”现有的计时器,这样如果您在同一个组件中多次使用它,就不会创建大量计时器。

    【讨论】:

      【解决方案8】:

      如果你想在 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

      【讨论】:

        【解决方案9】:

        设置定时器并在一定时间后自动呼叫服务

         // Initialize from ngInit
            ngOnInit(): void {this.getNotifications();}
            
            getNotifications() {
                setInterval(() => {this.getNewNotifications();
                }, 60000);  // 60000 milliseconds interval 
            }
            getNewNotifications() {
                this.notifyService.getNewNotifications().subscribe(
                    data => { // call back },
                    error => { },
                );
            }
        

        【讨论】:

          【解决方案10】:

          在最新版本的 Angular 上(我在 12.2.* 上工作)不支持 Observable.timer。您可以在 @Abdulrahman Alsoghayer 示例中稍作改动来使用它。

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-06-28
            • 2019-01-29
            • 2014-06-16
            • 1970-01-01
            • 2023-04-09
            • 2017-10-30
            • 2023-01-16
            • 1970-01-01
            相关资源
            最近更新 更多