Cách tạo bộ đếm thời gian trong angle2


95

Tôi cần một bộ đếm thời gian trong Angular 2, đánh dấu sau một khoảng thời gian và thực hiện một số tác vụ (có thể gọi một số chức năng).

Làm thế nào để làm điều này với Angular 2?


2
Chỉ bao gồm mã vừa đủ để cho phép người khác tái tạo sự cố. Để được trợ giúp về việc này, hãy đọc Cách tạo một ví dụ Tối thiểu, Hoàn chỉnh và Có thể xác minh. Nếu có thể tạo một ví dụ trực tiếp về vấn đề mà bạn có thể liên kết đến (ví dụ: trên sqlfiddle.com hoặc jsbin.com ) thì hãy làm như vậy - nhưng cũng bao gồm mã trong chính câu hỏi của bạn. Không phải ai cũng có thể truy cập các trang bên ngoài và các liên kết có thể bị hỏng theo thời gian.
Prasad

15
Đây thực sự là một câu hỏi rất hữu ích. Các vật quan sát rất quan trọng để tìm hiểu và sử dụng. Ngay cả khi người dùng không có mã để đi từ câu hỏi này sẽ hữu ích cho những người khác.
Winnemucca

Bình luận này rơi vào cùng một thùng, nhưng cả 2 người trước đó đều không giúp đỡ, chỉ bình luận về câu hỏi ... Rõ ràng bây giờ mọi người đang sử dụng lại setTimeout.
rbnzdave

setTimeout thực sự là một trường học cũ - hãy xem TimerObservable mới bên dưới
Philip

2
let this._timer = setInterval (() => this.getWidgetData (), 10000); và đảm bảo gọi clearInterval (this._timer); trên tiêu diệt
crh225,

Câu trả lời:


129

Ngoài tất cả các câu trả lời trước đó, tôi sẽ làm điều đó bằng cách sử dụng RxJS Observables

vui lòng kiểm tra Observable.timer

Đây là mã mẫu, sẽ bắt đầu sau 2 giây và sau đó tích tắc mỗi giây:

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

Và đây là một thợ đào đang hoạt động

Cập nhật Nếu bạn muốn gọi một hàm được khai báo trên lớp AppComponent, bạn có thể thực hiện một trong các thao tác sau:

** Giả sử hàm bạn muốn gọi có tên là func ,

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

Vấn đề với cách tiếp cận trên là nếu bạn gọi 'this' bên trong func, nó sẽ tham chiếu đến đối tượng người đăng ký thay vì đối tượng AppComponent có thể không phải là điều bạn muốn.

Tuy nhiên, trong cách tiếp cận dưới đây, bạn tạo một biểu thức lambda và gọi hàm func bên trong nó. Bằng cách này, lệnh gọi đến func vẫn nằm trong phạm vi của AppComponent. Đây là cách tốt nhất để làm điều đó theo ý kiến ​​của tôi.

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

kiểm tra mã hoạt động của plunker này .


Liệu tôi có thể chuyển một hàm tới `timer.subscribe (t => this.ticks = t);` được gọi trong mỗi lần đánh dấu không?
kuntal

@matrixwebtech Vâng, 't => this.ticks = t' là một biểu thức lambda, chính xác giống như 'function (t) {this.ticks = t}'
Abdulrahman Alsoghayer

Tôi thử timer.subscribe (function name () {console.log ("hhhhhh")}); cái nào hoạt động nhưng cách tôi gọi một hàm được khai báo riêng ngOnInit () {let timer = Observable.timer (2000,1000); timer.subscribe (function () {this.fun ();}); } fun () {console.log ("hhhhhh")}
kuntal

@matrixwebtech vui lòng kiểm tra câu trả lời cập nhật của tôi để biết ví dụ.
Abdulrahman alsoghayer,

1
@Notflip Dưới mui xe, timerdường như sử dụng setInterval(). Tuy nhiên, bạn có thể chuyển bộ lập animationFramelịch (mà sử dụng requestAnimationFrame()) để sử dụng nó thay vì bộ lập asynclịch mặc định . Tất cả những gì bạn cần làm là Observable.timer(*,*,Scheduler.animationFrame), mặc import {Scheduler} from ‘rxjs’dù, timernó dường như không hoạt động. Nó dường như vẫn sử dụng setInterVal(). Tuy nhiên, trên các loại có thể quan sát khác, chẳng hạn Observable.range(0,1000,Scheduler.animationFrame), requestAnimationFrameđược sử dụng chắc chắn. hiệu suất khôn ngoan, tôi không thể trả lời bạn chắc chắn ngay bây giờ.
Abdulrahman alsoghayer 21/02/17

79

Một giải pháp khác là sử dụng TimerObservable

TimerObservable là một lớp con của 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();
  }
}

Tái bút: Đừng quên hủy đăng ký.


3
phần hủy đăng ký là chìa khóa
Tucker

làm thế nào để bạn hủy đăng ký? và khi?
Miguel Stevens

1
@Notflip ngOnDestroy được gọi trong quá trình this.subscription.unsubscribe();hủy đăng ký thành phần: hủy đăng ký.
Philip

Làm cách nào để bạn có thể sử dụng this.subscription mà không cần tham khảo nó ở trên?
Winnemucca

2
Làm thế nào để bạn tạm dừng và khởi động lại nó?
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
Điều này không thêm bất cứ điều gì chưa được giải thích trong các câu trả lời khác, hoặc nó có?
Günter Zöchbauer

5

Với rxjs 6.2.2 và Angular 6.1.7, tôi nhận được:

Observable.timer is not a function

lỗi. Điều này đã được giải quyết bằng cách thay thế Observable.timerbằng 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
Để hủy đăng ký, bạn phải có một biến đăng ký như @ alexis-poo ở trên. Xem: stackoverflow.com/questions/40181169/… . Tôi căn cứ vào câu trả lời này của bạn không hoạt động như được viết về vấn đề đó.
Reid

Tôi yêu anh chàng này, người luôn cập nhật các Bài đăng lên các phiên bản Angular mới nhất ... Mỗi khi phải vật lộn với AngularJS và Angular. Cảm ơn anh bạn!
chainstair

4

Bạn có thể chỉ cần sử dụng tiện ích setInterval và sử dụng hàm mũi tên làm lệnh gọi lại để nó thissẽ trỏ đến cá thể thành phần.

Đối với ví dụ:

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

Bên trong móc vòng đời ngOnDestroy của bạn, xóa khoảng thời gian.

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

3

Tôi gặp phải một vấn đề là tôi phải sử dụng bộ hẹn giờ, nhưng tôi phải hiển thị chúng trong 2 thành phần cùng một lúc, cùng một màn hình. Tôi đã tạo bộ hẹn giờ Có thể quan sát trong một dịch vụ. Tôi đã đăng ký bộ hẹn giờ trong cả hai thành phần và điều gì đã xảy ra? Nó sẽ không được đồng bộ hóa, vì đăng ký mới luôn tạo luồng riêng.

Điều tôi muốn nói, là nếu bạn định sử dụng một bộ đếm thời gian ở một số nơi, hãy luôn đặt .publishReplay(1).refCount() ở cuối Trình quan sát, vì nó sẽ xuất bản cùng một luồng ra khỏi đó mọi lúc.

Thí dụ:

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

bạn có thể chia sẻ bạn cách thực hiện?
Nitish Kumar

1

Đã tìm thấy một gói npm giúp việc này trở nên dễ dàng với RxJS như một dịch vụ.

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

Bạn có thể 'đăng ký' vào một bộ đếm thời gian hiện có để không tạo ra một bộ hẹn giờ bazillion nếu bạn đang sử dụng nó nhiều lần trong cùng một thành phần.


1

Nếu bạn muốn chạy một phương thức trên ngOnInit, bạn có thể làm như sau:

nhập 2 thư viện này từ RXJS:

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

Sau đó khai báo bộ hẹn giờ và đăng ký riêng tư, ví dụ:

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

Phương pháp chạy cuối cùng nhưng không kém phần quan trọng khi bộ đếm thời gian dừng

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

Đó là tất cả, 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 => { },
    );
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.