web-dev-qa-db-ja.com

RxJS Observablesでカウントダウンタイマーを作る方法は?

Observablesを使用してカウントダウンタイマーを作成するのに苦労しています。 http://reactivex.io/documentation/operators/timer.html の例は機能していないようです。この特定の例では、timerIntervalに関連するエラーは、timerから返されたObservableの関数ではありません。

私は他のアプローチも実験しており、私が思いついた最善の方法は次のとおりです。

Observable.interval(1000).take(10).subscribe(x => console.log(x));

ここでの問題は、0から10までカウントアップすることです。 10,9,8 ... 0。

私もこれを試しましたが、timerはタイプObservableには存在しません

Observable.range(10, 0).timer(1000).subscribe(x => console.log(x));

同様に、出力をまったく生成しません。

Observable.range(10, 0).debounceTime(1000).subscribe(x => console.log(x));

明確にするために、MircoSoftバージョンではなく、ReactiveXのRxJS実装のヘルプが必要です。

17
Jonathan Miles

あなたは正しい軌道に乗っていました-あなたの問題はtimerがプロトタイプ(そしてObservable.range())に存在せず、Observableに存在することでした(RxJS docs を参照) )。つまり jsbin

const start = 10;
Rx.Observable
  .timer(100, 100) // timer(firstValueDelay, intervalBetweenValues)
  .map(i => start - i)
  .take(start + 1)
  .subscribe(i => console.log(i));

// or
Rx.Observable
  .range(0, start + 1)
  .map(i => start - i)
  .subscribe(i => console.log(i));
23
Niklas Fasching

間隔を使用すると、1秒の長さを指定できます

const time = 5 // 5 seconds
var timer$ = Rx.Observable.interval(1000) // 1000 = 1 second
timer$
  .take(time)
  .map((v)=>(time-1)-v) // to reach zero
  .subscribe((v)=>console.log('Countdown', v))
3
Zafer Qadi

私はtake...()の恋人なので、次のようにtakeWhile()を使用しています(RxJS 6.x.x、ES6の方法で)

import {timer} from 'rxjs';
import {takeWhile, tap} from 'rxjs/operators';


let counter = 10;
timer(1000, 1000) //Initial delay 1 seconds and interval countdown also 1 second
  .pipe(
    takeWhile( () => counter > 0 ),
    tap(() => counter--)
  )
  .subscribe( () => {
    console.log(counter);
  } );
1
Bayu

表示時間のあるカウンターダウン機能:

import { Observable, timer, of, interval } from "rxjs";
import { map, takeWhile, take } from "rxjs/operators";

function countdown(minutes: number, delay: number = 0) {
   return new Observable<{ display: string; minutes: number; seconds: number }>(
      subscriber => {
        timer(delay, 1000)
          .pipe(take(minutes * 60))
          .pipe(map(v => minutes * 60 - 1 - v))
          .pipe(takeWhile(x => x >= 0))
          .subscribe(countdown => { // countdown => seconds
            const minutes = Math.floor(countdown / 60);
            const seconds = countdown - minutes * 60;

            subscriber.next({
              display: `${("0" + minutes.toString()).slice(-2)}:${("0" + seconds.toString()).slice(-2)}`,
              minutes,
              seconds
            });

            if (seconds <= 0 && minutes <= 0) {
              subscriber.complete();
            }
       });
   });
}

countdown(2).subscribe(next => {
  document.body.innerHTML = `<pre><code>${JSON.stringify(next, null, 4)}</code></pre>`;
});

出力:

{
   "display": "01:56",
   "minutes": 1,
   "seconds": 56
}
1
anlijudavid

timerscantakeWhileを使用して、開始時間を変数に依存させたくない場合は、scanの3番目の引数が開始です数

timer$ = timer(0, 1000).pipe(
  scan(acc => --acc, 120),
  takeWhile(x => x >= 0)
);

Stackblitzで確認してください

0
Matt Bogenhagen