4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

オフグリッドAdvent Calendar 2024

Day 8

Observableとasync/awaitの違いを理解する

Last updated at Posted at 2024-12-10

Observableとasync/awaitの違いを理解する

はじめに

AngularやTypeScriptでは、非同期処理を扱う際に主に以下の2つのパターンが使われます:

  1. Observable(RxJS)
  2. async/await(Promiseベース)

両者は非同期処理を扱うための方法ですが、それぞれに特徴や適した場面があります。この記事では、両者の基本的な使い方と、それぞれを使った非同期処理の実装例を解説します。


目次

  1. Observableの基本
  2. async/awaitの基本
  3. Observableとasync/awaitの実践例
  4. どちらを使うべきか?場面ごとの選択

1. Observableの基本

ObservableはRxJSライブラリによって提供される非同期処理のツールです。特徴として、ストリーム(複数の値を時間に沿って配信)を扱える点があります。

基本的な使い方

import { Observable } from 'rxjs';

const observable = new Observable<number>((observer) => {
  observer.next(1);  // 値を送信
  observer.next(2);
  observer.complete(); // 完了
});

observable.subscribe({
  next: (value) => console.log(value), // 値を受け取る
  complete: () => console.log('Completed'), // 完了時に呼ばれる
});

2. async/awaitの基本

async/awaitは、Promiseを使って非同期処理を直感的に記述できる方法です。一度に単一の値を扱います。

基本的な使い方

const asyncFunction = async (): Promise<number> => {
  return new Promise((resolve) => {
    setTimeout(() => resolve(42), 1000);
  });
};

(async () => {
  const result = await asyncFunction();
  console.log(result); // 42
})();

3. Observableとasync/awaitの実践例

以下では、APIからデータを取得するシナリオで、Observableとasync/awaitを使った例を比較します。


Observableパターン

AngularでHttpClientを使う場合、HttpClientメソッドはObservableを返します。

import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class DataService {
  constructor(private http: HttpClient) {}

  // Observableを返す
  fetchData(): Observable<any> {
    return this.http.get('https://jsonplaceholder.typicode.com/posts');
  }
}

// 使用例
import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-my-component',
  template: '<div *ngFor="let post of posts">{{ post.title }}</div>',
})
export class MyComponent implements OnInit {
  posts: any[] = [];

  constructor(private dataService: DataService) {}

  ngOnInit(): void {
    this.dataService.fetchData().subscribe((data) => {
      this.posts = data;
    });
  }
}

async/awaitパターン

ObservablePromiseに変換することで、async/awaitスタイルで同じ処理を記述できます。

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class DataService {
  constructor(private http: HttpClient) {}

  // Promiseを返す
  async fetchData(): Promise<any> {
    return this.http.get('https://jsonplaceholder.typicode.com/posts').toPromise();
  }
}

// 使用例
import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-my-component',
  template: '<div *ngFor="let post of posts">{{ post.title }}</div>',
})
export class MyComponent implements OnInit {
  posts: any[] = [];

  constructor(private dataService: DataService) {}

  async ngOnInit(): Promise<void> {
    this.posts = await this.dataService.fetchData();
  }
}

4. どちらを使うべきか?場面ごとの選択

特徴 Observable async/await
複数の値を扱う 複数の値(ストリーム)を処理可能 単一の値の処理に最適
リアルタイム処理 WebSocketやイベントリスナーに最適 不向き
シンプルな処理 サブスクリプションが必要なため、やや複雑 簡潔で読みやすい
Angular推奨 HttpClientはデフォルトでObservableを返す ObservableをPromiseに変換すれば利用可能

Observableが適している場面

  • ストリームデータ: WebSocketやユーザーイベントなどの連続的なデータ。
  • リアクティブプログラミング: データの流れや変化を監視する必要がある場合。

async/awaitが適している場面

  • 単発の非同期操作: シンプルなAPI呼び出しやデータ取得。
  • 可読性が重要: 簡単な非同期処理を記述する際に最適。

おわりに

Observableは柔軟で強力ですが、特定の場面ではasync/awaitの方がシンプルに記述できます。どちらを使うべきかは、プロジェクトの要件や非同期処理の特性に応じて選択することが重要です。この記事を参考に、あなたのプロジェクトで適切な方法を選んでみてください!


番外編

Observableasync/await として扱うために使用する主要なメソッドは、firstValueFromlastValueFrom です。これらを紹介します。

1. firstValueFrom

firstValueFrom は、Observable の最初の値を Promise として取得するためのメソッドです。Observable が発行するデータの中で最初に出た値を取得し、Promise を解決します。

使用例:

import { Observable, firstValueFrom } from 'rxjs';

async function getFirstValue() {
  const observable = new Observable<number>((subscriber) => {
    subscriber.next(1);
    subscriber.next(2);
    subscriber.complete();
  });

  const value = await firstValueFrom(observable);
  console.log(`First value: ${value}`); // 出力: First value: 1
}

getFirstValue();

2. lastValueFrom

lastValueFrom は、Observable の最後の値を Promise として取得するためのメソッドです。Observable が完了するまで待機し、最後に発行された値を取得して Promise を解決します。

使用例:

import { Observable, lastValueFrom } from 'rxjs';

async function getLastValue() {
  const observable = new Observable<number>((subscriber) => {
    subscriber.next(1);
    subscriber.next(2);
    subscriber.next(3);
    subscriber.complete();
  });

  const value = await lastValueFrom(observable);
  console.log(`Last value: ${value}`); // 出力: Last value: 3
}

getLastValue();

まとめ

  • firstValueFrom: Observable の最初の値を Promise として非同期処理で取得する。
  • lastValueFrom: Observable の最後の値を Promise として非同期処理で取得する。

どちらも、Observableasync/await で扱いたい場合に非常に便利なメソッドです。これにより、RxJS のストリームをシンプルな非同期処理として扱うことができます。

4
0
2

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
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?