Angular toSignal และ toObservable: เชื่อม RxJS กับ Signals

#angular12 เม.ย. 2569

ทำไมต้องเชื่อม RxJS กับ Signals

Angular มีทั้ง RxJS Observables และ Signals ซึ่งเป็น reactive system สองแบบ Angular 16+ มี utility functions สำหรับแปลงระหว่างกัน

toSignal() — Observable → Signal

import { toSignal } from '@angular/core/rxjs-interop';
import { inject } from '@angular/core';

@Component({
  template: `
    <p>{{ users() | json }}</p>
    <p>{{ currentUser()?.name }}</p>
  `
})
export class UserComponent {
  private userService = inject(UserService);
  private route = inject(ActivatedRoute);

  // แปลง Observable เป็น Signal
  users = toSignal(this.userService.getUsers(), {
    initialValue: []
  });

  // จาก route params
  userId = toSignal(this.route.params.pipe(map(p => p['id'])));

  // computed จาก signal
  currentUser = computed(() =>
    this.users().find(u => u.id === this.userId())
  );
}

toObservable() — Signal → Observable

import { toObservable } from '@angular/core/rxjs-interop';

@Component({ ... })
export class SearchComponent {
  searchQuery = signal('');

  // แปลง Signal เป็น Observable เพื่อใช้ RxJS operators
  results = toSignal(
    toObservable(this.searchQuery).pipe(
      debounceTime(300),
      distinctUntilChanged(),
      filter(q => q.length >= 2),
      switchMap(q => this.searchService.search(q))
    ),
    { initialValue: [] }
  );
}

takeUntilDestroyed

import { takeUntilDestroyed } from '@angular/core/rxjs-interop';

@Component({ ... })
export class MyComponent {
  constructor() {
    // ไม่ต้องจัดการ unsubscribe เอง
    this.userService.getUsers()
      .pipe(takeUntilDestroyed())
      .subscribe(users => this.users.set(users));
  }
}

outputFromObservable

import { outputFromObservable } from '@angular/core/rxjs-interop';

@Component({ ... })
export class TimerComponent {
  private tick$ = interval(1000);
  tick = outputFromObservable(this.tick$);
}

สรุป

toSignal และ toObservable เป็น bridge ระหว่าง RxJS และ Signals ช่วยให้ migrate code ทีละส่วนได้โดยไม่ต้อง rewrite ทั้งหมดครับ