2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

**「Google流リアクティブプログラミング実践講座:RxJSで実現する非同期処理の極意」**

Posted at

はじめに

現代のWebアプリケーションでは、ユーザーイベント、API通信、状態管理など、非同期処理が複雑に絡み合います。Googleでは、YouTubeのリアルタイム更新やGoogleドライブの同期処理など、リアクティブプログラミングが重要な役割を果たしています。本記事では、Googleのプロダクト開発で実際に使用されているRxJSを中心に、実務で役立つリアクティブプログラミングのテクニックを解説します。


1. リアクティブプログラミングとは?

リアクティブプログラミングは、データストリーム変更伝搬を中心としたパラダイムです。

従来のコールバック vs リアクティブ

コールバック地獄

getUser(userId, function(user) {  
  getPosts(user, function(posts) {  
    getComments(posts, function(comments) {  
      // さらにネスト...  
    });  
  });  
});  

RxJSを使ったリアクティブな処理

getUser(userId)  
  .pipe(  
    switchMap(user => getPosts(user)),  
    switchMap(posts => getComments(posts))  
  )  
  .subscribe(comments => console.log(comments));  

2. GoogleプロダクトでのRxJS活用事例

事例1:YouTubeのリアルタイム検索

  • ユーザーが検索ボックスに入力するたびにAPIリクエストを発行
  • debounceTimeで連続入力を抑制
  • distinctUntilChangedで同一クエリの重複リクエストを防止
searchInput.valueChanges  
  .pipe(  
    debounceTime(300),  
    distinctUntilChanged(),  
    switchMap(query => fetchSearchResults(query))  
  )  
  .subscribe(results => updateUI(results));  

事例2:Googleドライブのファイル同期

  • 複数のファイル操作イベントをマージ
  • ネットワーク状態に応じてリトライ処理を実装
merge(  
  fileCreate$,  
  fileUpdate$,  
  fileDelete$  
).pipe(  
  concatMap(fileEvent => syncWithServer(fileEvent).pipe(  
    retryWhen(errors => errors.pipe(delay(1000), take(3))  
  ))  
).subscribe();  

3. RxJSオペレータの実践的使い分け

主要オペレータ比較表

オペレータ 用途 Googleでの使用例
switchMap 最新のリクエストのみ処理 検索入力
mergeMap 並列処理 通知送信
concatMap 順序保持 ファイルアップロード
exhaustMap 処理中のリクエストを無視 送信ボタン連打防止

4. エラーハンドリングのベストプラクティス

Googleでは、**「エラーもデータストリームの一部」**として扱います。

リトライ戦略の実装例

const MAX_RETRIES = 3;  

apiRequest$  
  .pipe(  
    retryWhen(errors => errors.pipe(  
      mergeMap((error, attempt) => {  
        if (attempt >= MAX_RETRIES || !isRetriable(error)) {  
          return throwError(() => error);  
        }  
        return timer(attempt * 1000);  
      })  
    ))  
  .subscribe();  

5. パフォーマンス最適化テクニック

メモリリーク防止

  • unsubscribeの自動化
@Component({...})  
export class MyComponent implements OnInit, OnDestroy {  
  private destroy$ = new Subject<void>();  

  ngOnInit() {  
    data$  
      .pipe(takeUntil(this.destroy$))  
      .subscribe();  
  }  

  ngOnDestroy() {  
    this.destroy$.next();  
    this.destroy$.complete();  
  }  
}  

サンプリングによる負荷軽減

highFrequencyData$  
  .pipe(sampleTime(200))  
  .subscribe();  

6. テスト戦略

Googleでは、**「Marble Testing」**と呼ばれる手法でRxJSのストリームをテストします。

テスト例

it('should debounce input', () => {  
  const input$ = cold('a---b---c|', {a: 'A', b: 'B', c: 'C'});  
  const expected = cold('------c|', {c: 'C'});  

  const result = input$.pipe(  
    debounceTime(20, testScheduler)  
  );  

  expectObservable(result).toBe(expected);  
});  

おわりに

リアクティブプログラミングは、**「複雑な非同期処理を宣言的に記述」**できる強力なパラダイムです。Googleでは、大規模アプリケーションの状態管理からマイクロサービス間の通信まで、幅広く活用されています。

次回は、**「「Kubernetesのアーキテクチャを完全理解!実践ガイド付き」」**を解説予定です!

「実際のプロジェクトでRxJSを使った面白い実装例があれば、コメントで教えてください!」 💡

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?