web-dev-qa-db-ja.com

RxJSで特定の時間量で観測可能な値を分離する

特定の時間までにObservableの値を生成する最も慣用的な方法は何でしょうか?たとえば、大きな配列から作成されたObservableがあり、2秒ごとに値を生成したいとします。 intervalselectManyの組み合わせが最善の方法ですか?

29
Sergi Mansilla

特定の例の場合、アイデアは、配列の各値を遅延後に結果を生成するオブザーバブルにマッピングし、結果のオブザーバブルのストリームを連結することです。

var delayedStream = Rx.Observable
    .fromArray([1, 2, 3, 4, 5])
    .map(function (value) { return Rx.Observable.return(value).delay(2000); })
    .concatAll();

他の例では、実際にtimerまたはintervalを使用する場合があります。状況次第です。

たとえば、配列が実際に非常に大きい場合、上記によりかなりのメモリプレッシャーが生じます(非常に大きいNに対してNオブザーバブルを作成しているため)。以下は、intervalを使用して配列を遅延ウォークする別の方法です。

var delayedStream = Rx.Observable
    .interval(2000)
    .take(reallyBigArray.length) // end the observable after it pulses N times
    .map(function (i) { return reallyBigArray[i]; });

これは、配列全体を反復するまで、2秒ごとに配列から次の値を生成します。

31
Brandon

Zipを使用すると、より優れた読みやすいコードが生成され、まだ3つのオブザーバブルのみを使用すると思います。

var items = ['A', 'B', 'C'];

Rx.Observable.Zip(
  Rx.Observable.fromArray(items),
  Rx.Observable.timer(2000, 2000),  
  function(item, i) { return item;}
)
24
farincz

ブランドンの答えはアイデアの要点を取得しますが、次のバージョンは最初のアイテムをすぐに生成し、次のアイテムの間に時間を置きます。

var delay = Rx.Observable.empty().delay(2000);

var items = Rx.Observable.fromArray([1,2,3,4,5])
  .map(function (x) {
    return Rx.Observable.return(x).concat(delay); // put some time after the item
  })
  .concatAll();

新しいRxJS用に更新:

var delay = Rx.Observable.empty().delay(2000);

var items = Rx.Observable.fromArray([1,2,3,4,5])
  .concatMap(function (x) {
    return Rx.Observable.of(x).concat(delay); // put some time after the item
  });
8
cwharris

RxJS 5の場合:

Rx.Observable.from([1, 2, 3, 4, 5])
  .Zip(Rx.Observable.timer(0, 2000), x => x)
  .subscribe(x => console.log(x));
5
user3587412

これは言及されていなかったので、 concatMap と組み合わせた delay はかなり読みやすいと思います。

Rx.Observable.fromArray([1, 2, 3, 4, 5])
    .concatMap(x => Rx.Observable.of(x).delay(1000));

https://codepen.io/jmendes/pen/EwaPzw を参照してください

4
Juan Mendes

Zipはクリーンなアプローチであることに同意します。配列の間隔ストリームを生成する再利用可能な関数は次のとおりです。

_function yieldByInterval(items, time) {
  return Rx.Observable.from(items).Zip(
    Rx.Observable.interval(time),
    function(item, index) { return item; }
  );
}

// test
yieldByInterval(['A', 'B', 'C'], 2000)
  .subscribe(console.log.bind(console));
_

これは farinczの答え に基づいていますが、インスタンスメソッドとして_.Zip_を使用することにより、少し短くなっています。

また、Rx.Observable.from()非推奨 であるため、Rx.Observable.fromArray()を使用しました。

4
Robert Penner

RxJS v6の場合、2秒の遅延で次のバージョンを取得します。

例1。 concatMap:

import {of} from 'rxjs';
import {concatMap, delay} from 'rxjs/operators';

of(1, 2, 3, 4, 5)
  .pipe(
    concatMap(x => of(x)
      .pipe(
        delay(2000))
    )
  )
  .subscribe({
    next(value) {
      console.log(value);
    }
  });

例2。マップ+ concatAll:

import {of} from 'rxjs';
import {concatAll, delay, map} from 'rxjs/operators';

of(1, 2, 3, 4, 5)
  .pipe(
    map(x => of(x)
      .pipe(
        delay(2000))
    ),
    concatAll()
  )
  .subscribe({
    next(value) {
      console.log(value);
    }
  });
1
ZoomAll

Farinczとuser3587412によるZipソリューションを基にした、RxJS v6での動作

const { Zip, from, timer } = require("rxjs")
const { map } = require("rxjs/operators")

const input = [1, 2, 3, 4, 5]
const delay = 2000

Zip(
    from(input),
    timer(0, delay)
).pipe(
    map(([ delayedInput, _timer ]) => delayedInput) // throw away timer index
).subscribe(
    console.log
)
0
Anonymous