วิธีสร้างตัวจับเวลาในเชิงมุม 2


97

ฉันต้องการตัวจับเวลาใน Angular 2 ซึ่งทำเครื่องหมายหลังจากช่วงเวลาและทำงานบางอย่าง (อาจเรียกใช้ฟังก์ชันบางอย่าง)

จะทำอย่างไรกับ Angular 2?


2
ใส่รหัสเพียงพอที่จะอนุญาตให้ผู้อื่นจำลองปัญหาได้ หากต้องการความช่วยเหลือโปรดอ่านวิธีสร้างตัวอย่างขั้นต่ำสมบูรณ์และตรวจสอบได้ หากเป็นไปได้ที่จะสร้างตัวอย่างจริงของปัญหาที่คุณสามารถเชื่อมโยงไปได้ (ตัวอย่างเช่นในsqlfiddle.comหรือjsbin.com ) ให้ทำเช่นนั้น - แต่ยังรวมรหัสไว้ในคำถามของคุณด้วย ไม่ใช่ทุกคนที่สามารถเข้าถึงไซต์ภายนอกได้และลิงก์อาจพังเมื่อเวลาผ่านไป
ปรา

15
นี่เป็นคำถามที่มีประโยชน์มาก Observables เป็นสิ่งสำคัญในการเรียนรู้และใช้งาน แม้ว่าผู้ใช้จะไม่มีรหัสไปจากคำถามนี้ก็จะเป็นประโยชน์ต่อผู้อื่น
Winnemucca

ความคิดเห็นนี้อยู่ในที่เก็บข้อมูลเดียวกัน แต่ทั้ง 2 คนก่อนหน้านี้ไม่ได้ช่วยอะไรเลยเพิ่งแสดงความคิดเห็นในคำถาม ... เห็นได้ชัดว่ามีคนใช้ setTimeout อีกครั้งในขณะนี้
rbnzdave

setTimeout เป็นโรงเรียนเก่าจริงๆ - ดู Timer สดใหม่ด้านล่าง
Philip

2
ปล่อยให้ this._timer = setInterval (() => this.getWidgetData (), 10000); และตรวจสอบให้แน่ใจว่าได้เรียก clearInterval (this._timer); เมื่อทำลาย
crh225

คำตอบ:


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

และนี่คือPlunker ที่ใช้งานได้

อัปเดต หากคุณต้องการเรียกใช้ฟังก์ชันที่ประกาศในคลาส AppComponent คุณสามารถดำเนินการอย่างใดอย่างหนึ่งต่อไปนี้:

** สมมติว่าฟังก์ชั่นที่คุณต้องการที่จะเรียกเป็นชื่อfunc ,

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

ปัญหาเกี่ยวกับวิธีการข้างต้นคือถ้าคุณเรียก 'this' ภายใน func มันจะอ้างถึงวัตถุสมาชิกแทนที่จะเป็นวัตถุ AppComponent ซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ

อย่างไรก็ตามในแนวทางด้านล่างคุณสร้างนิพจน์แลมบ์ดาและเรียกใช้ฟังก์ชันfunc ที่อยู่ภายใน วิธีนี้การเรียกใช้ func ยังคงอยู่ในขอบเขตของ AppComponent นี่เป็นวิธีที่ดีที่สุดในความคิดของฉัน

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

ตรวจสอบplunker นี้สำหรับรหัสการทำงาน


ฉันควรจะส่งฟังก์ชั่นไปที่ `timer.subscribe (t => this.ticks = t);` ที่เรียกในทุกเห็บได้หรือไม่?
kuntal

@matrixwebtech ใช่ 't => this.ticks = t' เป็นนิพจน์แลมบ์ดาเหมือนกับ 'function (t) {this.ticks = t}'
Abdulrahman Alsoghayer

ฉันลอง timer.subscribe (ชื่อฟังก์ชัน () {console.log ("hhhhhh")}); ซึ่งทำงาน แต่ฉันเรียกใช้ฟังก์ชันที่ประกาศแยกต่างหาก ngOnInit () {let timer = Observable.timer (2000,1000); timer.subscribe (ฟังก์ชัน () {this.fun ();}); } fun () {console.log ("hhhhhh")}
kuntal

@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

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
ส่วนการยกเลิกการสมัครเป็นกุญแจสำคัญ
ทักเกอร์

คุณจะยกเลิกการสมัครได้อย่างไร? และเมื่อ?
Miguel Stevens

1
@Notflip ngOnDestroy ถูกเรียกในระหว่างthis.subscription.unsubscribe();การยกเลิกส่วนประกอบ: ยกเลิกการสมัคร
Philip

คุณจะใช้สิ่งนี้ได้อย่างไรการสมัครสมาชิกโดยไม่ต้องอ้างอิงด้านบน
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
สิ่งนี้ไม่ได้เพิ่มสิ่งที่ยังไม่ได้อธิบายในคำตอบอื่น ๆ หรือไม่?
GünterZöchbauer

7

ด้วย 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();    
}

3
ในการยกเลิกการสมัครคุณต้องมีตัวแปรการสมัครเช่น @ alexis-poo ด้านบน ดู: stackoverflow.com/questions/40181169/… . ฉันยึดตามคำตอบของคุณไม่ได้ผลตามที่เขียนไว้ในเรื่องนั้น
Reid

ฉันรักผู้ชายคนนี้ที่อัปเดตโพสต์เป็น Angular เวอร์ชันใหม่ล่าสุดอยู่เสมอ ... ทุกครั้งที่ต่อสู้กับ AngularJS และ Angular มากมาย ขอบคุณ!
chainstair

4

คุณสามารถใช้ยูทิลิตี้ setInterval และใช้ฟังก์ชันลูกศรเป็นการโทรกลับเพื่อที่thisจะชี้ไปที่อินสแตนซ์ของคอมโพเนนต์

สำหรับอดีต:

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

ภายในตะขอวงจรชีวิตของ ngOnDestroy ให้ล้างช่วงเวลา

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

3

ฉันประสบปัญหาที่ต้องใช้ตัวจับเวลา แต่ต้องแสดงเป็น 2 องค์ประกอบในเวลาเดียวกันหน้าจอเดียวกัน ฉันสร้างตัวจับเวลาที่สังเกตได้ในบริการ ฉันสมัครใช้งานตัวจับเวลาในทั้งสององค์ประกอบแล้วเกิดอะไรขึ้น จะไม่ถูกซิงค์เนื่องจากการสมัครใหม่จะสร้างสตรีมของตัวเองเสมอ

สิ่งที่ฉันอยากจะบอกก็คือถ้าคุณวางแผนที่จะใช้ตัวจับเวลาหนึ่งตัวในสถานที่ต่างๆให้วางไว้.publishReplay(1).refCount() ที่ส่วนท้ายของ Observer เสมอเพราะมันจะเผยแพร่สตรีมเดียวกันออกไปทุกครั้ง

ตัวอย่าง:

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

คุณสามารถแบ่งปันการใช้งานของคุณได้หรือไม่?
Nitish Kumar

1

พบแพ็คเกจ npm ที่ทำให้สิ่งนี้ง่ายขึ้นด้วย RxJS เป็นบริการ

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

คุณสามารถ 'สมัคร' ตัวจับเวลาที่มีอยู่เพื่อที่คุณจะได้ไม่ต้องสร้างตัวจับเวลาพันล้านหากคุณใช้มันหลายครั้งในส่วนประกอบเดียวกัน


1

หากคุณต้องการเรียกใช้เมธอดบน ngOnInit คุณสามารถทำสิ่งนี้ได้:

นำเข้า 2 ไลบรารีจาก RXJS:

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 => { },
    );
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.