iT邦幫忙

2026 iThome 鐵人賽

DAY 16
0
自我挑戰組

Angular 開發二三事系列 第 16 篇

Day16: Angular 的非同步處理

  • 分享至 

  • xImage
  •  

進入正題前,先來複習什麼是「同步」、「非同步」。

什麼是「同步」、「非同步」?

同步(Synchronous):

  • 定義: 程式碼是由上至下,一行、一行地執行的。必須等上一行完全結束並回傳結果,才能執行下一行。
  • 特性: 馬上就能得到資料,執行過程會阻塞(Block)後續程式碼。
  • 範例:
const a = 2;
const b = 3;
let total = a + b;
console.log(total);

非同步 (Asynchronous)

  • 定義: 執行一個任務後,讓程式碼繼續往下跑,等到資料回來時才回調(Callback)、Promise......等觸發處理。
  • 特性: 不會阻塞畫面的渲染與其他程式執行,是處理網路請求、計時器(setTimeout)的標準方式。
  • 工具:
    • Promise: JavaScript 處理非同步的物件,代表一個尚未完成,但未來會產生成果或失敗的的操作,可以用 .then() 串接。
    • Async/Await: Promise 的語法糖,讓非同步程式碼看起來像同步程式碼一樣直覺易讀。
    • Fetch API: 瀏覽器內建用來發送網路請求(AJAX)的標準介面,會回傳 Promise。
    • setTimeout / setInterval: 用來安排延遲或定期執行任務的計時器函式。
    • RxJS Observable: Angular 最常用的非同步資料流工具,支援強力運算子。

Angular 的非同步處理

複習完「同步」、「非同步」之後,我們來認識 Angular 自己使用的非同步工具 RxJS Observable。

什麼是 RxJS Observable?

我們一個個透過名詞解釋來了解:

  • RxJS: ReactiveX 的 JavaScript 實現版本,透過組合一些常用的程式技巧,來處理「非同步」及「串流(或事件)」,讓程式碼更好理解、也更容易維護。
  • Observable: 「可被觀察的」,就是一個可被觀察的對象,這個對象可以是任何東西(例如監聽的 click 事件),當有新資料的時候(新的點擊事件),可以接收到這個新資料的資訊並且做出反應。
  • Observer: 「觀察者」,當上方的「可被觀察」觸發事件後,「觀察者」就可以做出反應。
  • Subscribe: 「訂閱」,「觀察者」的行為。情境上為,當 Observable 使用訂閱 Subscribe 之後,即可追蹤資料變動做對應的更新。

Subscribe 的三種訊息:

Subscribe 訂閱一個 Observable 時(可以說是「監視」Observable 時XD),會回傳三種狀態:

  • next():發送下一個資料。
  • complete():發送完成訊號,資料流結束,不會有新資料。
  • error():發送錯誤訊號,終止資料流。

三種狀態可以想像成 try、catch、finally 唷!

實作:

我們拿封裝好的 ApiServer 來執行非同步:

import { inject, signal } from '@angular/core';
import { AlertService } from '@/app/core';
import { ApiService } from '@/app/api';

export class Product {
  private readonly alertService = inject(AlertService);
  private readonly apiService = inject(ApiService);
  readonly productList = signal<ProductType[]>([]);
  
  protected refreshCaptcha(): void {
    this.apiService.getProduct().subscribe({
      next: (data: ProductType[]) => {
        this.productList.set(data);
      },
      error: (err) => {
        this.alertService.toastError(`請求錯誤!`)
      },
      complete: () => {
        console.log('整個請求流程完成!')
      }
  }
}

‼️重要‼️: 記得取消訂閱(Unsubscribe)

如果元件被銷毀(Destroy)時沒有取消訂閱,非同步任務可能會持續在背景執行,導致記憶體洩漏(Memory Leak)。

import { Component, OnInit, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs';
import { UserService } from './user.service';

@Component({ ... })
export class UserComponent implements OnInit, OnDestroy {
  users: any[] = [];
  private sub!: Subscription;

  constructor(private userService: UserService) {}

  ngOnInit() {
    // 手動訂閱並將資料賦值給本地變數
    this.sub = this.userService.getUsers().subscribe(data => {
      this.users = data;
    });
  }

  ngOnDestroy() {
    // 必須手動取消訂閱,否則會記憶體洩漏
    if (this.sub) this.sub.unsubscribe();
  }
}

就是這樣啦,一點一滴地釐清概念後,對 Angular 開發方式會更清楚唷!
繼續努力!


參考資料:


上一篇
Day 15: Angular 的網路請求 HTTP request
下一篇
Day17: Angular 的 Async / Await
系列文
Angular 開發二三事 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言