Как создать таймер в angular2


97

Мне нужен таймер в Angular 2, который тикает через временной интервал и выполняет некоторую задачу (может вызывать некоторые функции).

Как это сделать с Angular 2?


2
Включите ровно столько кода, чтобы позволить другим воспроизвести проблему. Чтобы получить помощь в этом, прочитайте, как создать минимальный, полный и проверяемый пример. Если возможно создать живой пример проблемы, на которую вы можете ссылаться (например, на sqlfiddle.com или jsbin.com ), сделайте это, но также включите код в сам вопрос. Не все могут получить доступ к внешним сайтам, и со временем ссылки могут сломаться.
Прасад

15
На самом деле это очень полезный вопрос. Наблюдаемые важно изучать и использовать. Даже если у пользователя не было кода для перехода, этот вопрос будет полезен другим.
Winnemucca

Этот комментарий попадает в ту же корзину, но ни один из предыдущих 2 человек не помог, просто прокомментировал вопрос ... Очевидно, люди теперь снова используют setTimeout.
rbnzdave

setTimeout действительно олдскульный - ознакомьтесь с новым TimerObservable ниже
Филип

2
пусть this._timer = setInterval (() => this.getWidgetData (), 10000); и обязательно вызовите clearInterval (this._timer); on destroy
crh225 09

Ответы:


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

Проблема с вышеуказанным подходом заключается в том, что если вы вызываете this внутри func, он будет ссылаться на объект подписчика, а не на объект AppComponent, что, вероятно, не то, что вам нужно.

Однако в приведенном ниже подходе вы создаете лямбда-выражение и вызываете внутри него функцию func . Таким образом, вызов func по-прежнему находится в области действия AppComponent. На мой взгляд, это лучший способ сделать это.

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

проверьте этот плункер на предмет рабочего кода.


Могу ли я передать функцию `timer.subscribe (t => this.ticks = t);`, которая вызывается в каждом тике?
kuntal 06

@matrixwebtech Да, 't => this.ticks = t' - это лямбда-выражение, точно такое же, как 'function (t) {this.ticks = t}'
Абдулрахман Альсогайер

Я пробую timer.subscribe (имя функции () {console.log ("hhhhhh")}); который работает, но как я вызываю функцию, которая объявлена ​​отдельно ngOnInit () {let timer = Observable.timer (2000,1000); timer.subscribe (функция () {this.fun ();}); } fun () {console.log ("hhhhhh")}
kuntal

@matrixwebtech, пожалуйста, проверьте мой обновленный ответ для примеров.
Абдулрахман 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используется. Что касается производительности, я не могу ответить вам точно прямо сейчас.
Абдулрахман 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
часть
Tucker

как отписаться? и когда?
Мигель Стивенс

1
@Notflip ngOnDestroy вызывается во время деинициализации компонента: this.subscription.unsubscribe();отпадает.
Филипп

Как вы можете использовать this.subscription, не ссылаясь на него выше?
Winnemucca

2
Как сделать паузу и перезапустить?
Дэни

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ünter Zöchbauer

6

С 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/… . Я основываю это на вашем ответе, который не работает так, как написано в этом отношении.
Рид

Мне нравится этот парень, который постоянно обновляет сообщения до новейших версий Angular ... Каждый раз так много проблем с AngularJS и Angular. Спасибо чувак!
цепная лестница

4

Вы можете просто использовать утилиту setInterval и использовать стрелочную функцию в качестве обратного вызова, чтобы thisона указывала на экземпляр компонента.

Например:

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

В хуке жизненного цикла ngOnDestroy очистите интервал.

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

3

Я столкнулся с проблемой, что мне пришлось использовать таймер, но мне пришлось отображать их в двух компонентах одновременно, на одном экране. Я создал timerObservable в сервисе. Я подписался на таймер в обоих компонентах, и что случилось? Он не будет синхронизирован, потому что новая подписка всегда создает свой собственный поток.

Я хотел бы сказать, что если вы планируете использовать один таймер в нескольких местах, всегда ставьте .publishReplay(1).refCount() в конец Observer, потому что он будет каждый раз публиковать из него один и тот же поток.

Пример:

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

можешь поделиться своей реализацией?
Нитиш Кумар

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 => { },
    );
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.