狐好きぷろぐらまー

狐好きプログラマーのブログです。

【0.23.0対応】rxdartについて調べてみる 第5回目 -Periodic, Never- 【rxdart】

こんばんは。 pregum_foxです。

前回に引き続きrxdartのオペレータを調べていきたいと思います。

今回は、rxdartのPeriodicオペレータとNeverオペレータについて調べていきます。

前回までの記事です。

目次です。

動作環境

動作環境は以下の通りです。

項目 バージョン
Dart 2.6.1
rxdart 0.24.0

この記事はrxdartが0.22.x以前のバージョンで書いていたこの記事を0.23.0以降のバージョンに対応した記事です。

0.22.xから0.23.xにバージョンが上がったタイミングの変更内容は以下のサイトをご覧ください。

以下にPeriodicオペレータとNeverオペレータについて記載します。

Periodic オペレータ (rxdart: Observable<T>.periodic ファクトリコンストラクタ / Stream API: Stream<T>.periodic ファクトリコンストラクタ)

rxdartのperiodicは削除されました。代わりにStream APIのStream.periodicを使用しましょう。

periodicは、Rxのコアのオペレータとしては存在していないようです。 ただ、いくつかのオペレータを組み合わせて代替することが可能です。(サンプルに代替版も記載します。)

シグネチャ

  • Stream API
    Stream<T> Stream<T>.periodic(Duration period, [T computation(int computationCount)])

処理の概要

periodicは、period間隔で繰り返し値を作成し、発行します。
発行する値は、値を作成するごとにインクリメントされていきます。
computationが省略されている場合は、nullが作成、発行されます。
サンプルを以下に示します。

/// Stream APIのperiodicサンプル
void studyPeriodicStream() {
  Stream<int>.periodic(Duration(milliseconds: 500), (i) => i + 3)
      .take(5)
      .listen(print, onDone: () => print('done.'));
}
// 実行結果
// 3
// 4
// 5
// 6
// 7
// done.

サンプルの実行結果から、Streamが作成される度に出力される数がインクリメントされていることが分かります。
定期的に値を発行したい場合は使えるかもしれません。

Never オペレータ (rxdart: Rx.never<T> 拡張メソッド / NeverStream<T> クラス)

シグネチャ

  • rxdart
    Stream<T> never<T>()

  • Stream API
    NeverStream<T> NeverStream<T>()

処理の概要

無限の期間を示す場合、使用することができます。
neverオペレータを使用した場合、終了しないためonDone処理も実行されません。
サンプルを以下に示します。

/// rxdartのNeverオペレータサンプル
void studyNever() {
  // neverオペレータで無限の期間を表現できます。
  // timeoutオペレータをchainすることで、時間切れを確実に起こすことができます。
  Rx.never()
      .timeout(Duration(seconds: 3),
          onTimeout: (err) => err.addError('time out error'))
      .listen((str) => print('listen: $str'),
          onError: (err) => print('error listen: $err'), cancelOnError: true);
}
// 実行結果
// error listen: time out error
  
/// Stream APIのNeverオペレータサンプル
void studyNeverStream() {
  NeverStream<String>()
      .timeout(Duration(seconds: 3),
          onTimeout: (err) => err.addError('time out error'))
      .listen((str) => print('listen: $str'),
          onError: (err) => print('error listen: $err'), cancelOnError: true);
}
// 実行結果
// error listen: time out error

サンプルの実行結果を見てもらうとわかるように、neverオペレータだけでは終了しないため、timeoutオペレータを組み合わせてtimeout時にerrorを起こすようにしています。

このような時間切れのテストを書く際に、neverオペレータを使用すれば簡単に実装することができます。

errorで終了する際は、cancelOnErrorをtrueする必要がある事にご注意ください。(デフォルトのfalseのままだと、onErrorの処理の後onDoneの処理が走ります。)

雑感

Rxの主要なオペレータを調べてrxdartの内容と見比べてみたりしていますが、対応するオペレータがまだわからないのでRxは調べれば調べるほど深みにはまっている感じがあります。。

ある程度のところでこの沼から脱出できることを思いながら調べていきたいと思います。

ここまで読んで頂き、ありがとうございました。

ここで書いたサンプルコードは以下のリポジトリから確認できます。

参考サイト