Skip to content

dematerialize - 通知オブジェクトの復元

dematerialize オペレーターは、Notification オブジェクトを通常の通知(next, error, complete)に変換します。materialize の逆変換を行い、データ化された通知を元の形式に戻します。

🔰 基本構文・動作

Notificationオブジェクトのストリームを通常のストリームに戻します。

ts
import { of } from 'rxjs';
import { materialize, dematerialize } from 'rxjs';

of(1, 2, 3)
  .pipe(
    materialize(),     // Notificationオブジェクトに変換
    dematerialize()    // 元に戻す
  )
  .subscribe({
    next: v => console.log('値:', v),
    complete: () => console.log('完了')
  });
// 出力:
// 値: 1
// 値: 2
// 値: 3
// 完了

🌐 RxJS公式ドキュメント - dematerialize

💡 典型的な活用例

  • 通知の加工後に復元: materializeで処理した後、元の形式に戻す
  • エラーのフィルタリング: 特定のエラーだけを除外
  • 通知の順序変更: 通知をデータとして並べ替えた後に復元
  • デバッグ後の復元: ログ出力などの処理後に通常動作に戻す

🧪 実践コード例1: エラーの選択的フィルタリング

特定のエラーだけを除外し、それ以外は通常通り処理する例です。

ts
import { of, throwError, concat } from 'rxjs';
import { materialize, dematerialize, filter } from 'rxjs';

// UI作成
const container = document.createElement('div');
document.body.appendChild(container);

const title = document.createElement('h3');
title.textContent = 'dematerialize - エラーフィルタリング';
container.appendChild(title);

const output = document.createElement('div');
output.style.border = '1px solid #ccc';
output.style.padding = '10px';
container.appendChild(output);

function addLog(message: string, color: string) {
  const logItem = document.createElement('div');
  logItem.style.padding = '5px';
  logItem.style.marginBottom = '3px';
  logItem.style.backgroundColor = color;
  logItem.textContent = message;
  output.appendChild(logItem);
}

// エラーを含むストリーム
const source$ = concat(
  of(1, 2),
  throwError(() => new Error('無視すべきエラー')),
  of(3, 4),
  throwError(() => new Error('重大なエラー')),
  of(5)
);

source$
  .pipe(
    materialize(),
    filter(notification => {
      // "無視すべきエラー"だけをフィルタリング
      if (notification.kind === 'E') {
        const errorMessage = notification.error?.message || '';
        if (errorMessage.includes('無視すべき')) {
          addLog(`🔇 無視: ${errorMessage}`, '#fff9c4');
          return false;  // このエラーは除外
        }
      }
      return true;
    }),
    dematerialize()  // 元の形式に戻す
  )
  .subscribe({
    next: v => addLog(`✅ 値: ${v}`, '#c8e6c9'),
    error: err => addLog(`❌ エラー: ${err.message}`, '#ffcdd2'),
    complete: () => addLog('完了', '#e3f2fd')
  });
  • "無視すべきエラー"は除外され、ストリームは継続
  • "重大なエラー"は通常通りエラーハンドラに渡される
  • エラーの選択的処理が可能

🧪 実践コード例2: 通知の遅延処理

通知を一時的にバッファリングしてから復元する例です。

ts
import { from, interval, take, delay } from 'rxjs';
import { materialize, dematerialize, bufferTime, concatMap } from 'rxjs';

// UI作成
const container2 = document.createElement('div');
container2.style.marginTop = '20px';
document.body.appendChild(container2);

const title2 = document.createElement('h3');
title2.textContent = 'dematerialize - バッファリングと遅延';
container2.appendChild(title2);

const output2 = document.createElement('div');
output2.style.border = '1px solid #ccc';
output2.style.padding = '10px';
output2.style.maxHeight = '200px';
output2.style.overflow = 'auto';
container2.appendChild(output2);

function addLog2(message: string) {
  const now = new Date();
  const timestamp = now.toLocaleTimeString('ja-JP', { hour12: false }) +
    '.' + now.getMilliseconds().toString().padStart(3, '0');

  const logItem = document.createElement('div');
  logItem.textContent = `[${timestamp}] ${message}`;
  output2.appendChild(logItem);
}

addLog2('開始 - 1秒ごとに値を発行、2秒ごとにまとめて処理');

interval(1000)
  .pipe(
    take(6),
    materialize(),
    bufferTime(2000),      // 2秒ごとにバッファ
    concatMap(notifications => {
      addLog2(`--- ${notifications.length}個の通知をバッファから処理 ---`);
      return from(notifications).pipe(
        delay(500),        // 各通知を0.5秒遅延
        dematerialize()    // 元の形式に戻す
      );
    })
  )
  .subscribe({
    next: v => addLog2(`値: ${v}`),
    complete: () => addLog2('完了')
  });
  • 通知を2秒ごとにバッファリング
  • バッファから取り出して遅延処理
  • dematerializeで元のストリームとして復元

🆚 materialize との関係

ts
import { of } from 'rxjs';
import { materialize, dematerialize, map } from 'rxjs';

of(1, 2, 3)
  .pipe(
    materialize(),           // Notificationに変換
    map(notification => {
      // Notificationオブジェクトとして処理
      console.log('kind:', notification.kind);
      return notification;
    }),
    dematerialize()          // 元に戻す
  )
  .subscribe(v => console.log('値:', v));
// 出力:
// kind: N
// 値: 1
// kind: N
// 値: 2
// kind: N
// 値: 3
// kind: C
処理の流れ説明
元のストリーム通常の値(next)、エラー(error)、完了(complete)
materialize()Notificationオブジェクトのストリーム
中間処理Notificationとして加工・フィルタリング
dematerialize()通常のストリームに復元
最終的なストリーム通常の値、エラー、完了

⚠️ 注意点

1. エラー通知は実際のエラーに変換される

ts
import { of, throwError, concat } from 'rxjs';
import { materialize, dematerialize } from 'rxjs';

// 各Observableをmaterialize()で通知オブジェクトに変換
concat(
  of(1).pipe(materialize()),
  throwError(() => new Error('エラー')).pipe(materialize()),
  of(2).pipe(materialize())  // エラー後なので実行されない
)
  .pipe(
    dematerialize()
  )
  .subscribe({
    next: v => console.log('値:', v),
    error: err => console.log('エラー:', err.message)
  });
// 出力:
// 値: 1
// エラー: エラー

エラー通知に到達すると、ストリームはエラーで中断されます。

2. 完了通知でストリームが完了する

ts
import { of, EMPTY, concat } from 'rxjs';
import { materialize, dematerialize } from 'rxjs';

// 各Observableをmaterialize()で通知オブジェクトに変換
concat(
  of(1).pipe(materialize()),
  of(2).pipe(materialize()),
  EMPTY.pipe(materialize()),  // 完了通知
  of(3).pipe(materialize())   // 完了後なので実行されない
)
  .pipe(
    dematerialize()
  )
  .subscribe({
    next: v => console.log('値:', v),
    complete: () => console.log('完了')
  });
// 出力:
// 値: 1
// 値: 2
// 完了

完了通知以降の値は発行されません。

3. 不正なNotificationオブジェクト

dematerializeは正しいNotificationオブジェクトを期待します。

ts
import { of } from 'rxjs';
import { dematerialize } from 'rxjs';

// ❌ 通常の値をdematerializeに渡すとエラー
of(1, 2, 3)
  .pipe(
    dematerialize()  // Notificationオブジェクトではない
  )
  .subscribe({
    next: console.log,
    error: err => console.error('エラー:', err.message)
  });
// エラーが発生

実践的な組み合わせ例

ts
import { interval, throwError, of, concat } from 'rxjs';
import { materialize, dematerialize, take, mergeMap, map } from 'rxjs';

// エラーをwarningに変換する例
interval(500)
  .pipe(
    take(10),
    mergeMap(value => {
      // 5の時だけエラーを発生
      if (value === 5) {
        return throwError(() => new Error(`値${value}でエラー`));
      }
      return of(value);
    }),
    materialize(),
    map(notification => {
      // エラーをwarningメッセージに変換
      if (notification.kind === 'E') {
        console.warn('Warning:', notification.error?.message);
        // エラーの代わりに特別な値を発行(materialize()で生成)
        return { kind: 'N' as const, value: -1 };
      }
      return notification;
    }),
    dematerialize()
  )
  .subscribe({
    next: v => console.log('値:', v),
    error: err => console.error('エラー:', err),  // 呼ばれない
    complete: () => console.log('完了')
  });
// 出力:
// 値: 0, 1, 2, 3, 4
// Warning: 値5でエラー
// 値: -1  (エラーの代わり)
// 値: 6, 7, 8, 9
// 完了

📚 関連オペレーター

  • materialize - 通知をNotificationオブジェクトに変換
  • catchError - エラーハンドリング
  • retry - エラー時の再試行

✅ まとめ

dematerialize オペレーターは、Notificationオブジェクトを通常の通知に戻します。

  • materializeの逆変換
  • ✅ 通知を加工した後に元の形式に復元
  • ✅ エラーのフィルタリングや変換が可能
  • ✅ 通知の順序変更やバッファリングに活用
  • ⚠️ エラー通知は実際のエラーとして動作
  • ⚠️ 完了通知でストリームが完了
  • ⚠️ 正しいNotificationオブジェクトが必要

Released under the CC-BY-4.0 license.