哈囉,各位邦友們!
昨天我們完成了 /detail/:id,並用 withComponentInputBinding() 讓路由參數直綁到元件。
今天會在專案中導入 provideHttpClient(),將 HeroService 改為透過 HttpClient 存取遠端 API,並先用 angular-in-memory-web-api 模擬後端。
angular-in-memory-web-api,建立 InMemoryDataService 當作假後端。app.config.ts 啟用 provideHttpClient(withFetch())。HeroService,以 HttpClient 實作 getAll$()、getById$(),並調整updateName(id: number, name: string)。一、安裝並建立 InMemory 假後端
npm i -D angular-in-memory-web-api
ng g serviice InMemoryData
// src/app/in-memory-data.ts
import { Injectable } from '@angular/core';
import { InMemoryDbService } from 'angular-in-memory-web-api';
export type Hero = { id: number; name: string; rank?: string };
@Injectable({
  providedIn: 'root'
})
export class InMemoryData implements InMemoryDbService {
	createDb() {
		const heroes: Hero[] = [
			{ id: 11, name: 'Dr Nice', rank: 'B' },
			{ id: 12, name: 'Narco', rank: 'A' },
			{ id: 13, name: 'Bombasto', rank: 'S' },
			{ id: 14, name: 'Celeritas', rank: 'A' },
			{ id: 15, name: 'Magneta', rank: 'B' },
		];
		return { heroes };
	}
}
二、在 app.config.ts 啟用 HttpClient 與 InMemory Web API
// src/app.config.ts
import { ApplicationConfig, importProvidersFrom, provideBrowserGlobalErrorListeners, provideZonelessChangeDetection } from '@angular/core';
import { provideClientHydration, withEventReplay } from '@angular/platform-browser';
import { provideRouter, withComponentInputBinding } from '@angular/router';
import { provideHttpClient, withFetch } from '@angular/common/http';
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { routes } from './app.routes';
import { InMemoryData } from './in-memory-data';
export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes, withComponentInputBinding()),
    provideBrowserGlobalErrorListeners(),
    provideZonelessChangeDetection(),
    provideHttpClient(withFetch()),
    importProvidersFrom(
      HttpClientInMemoryWebApiModule.forRoot(InMemoryData, {
        dataEncapsulation: false,
        delay: 300,
      })
    ),
    provideClientHydration(withEventReplay())
  ],
};
三、重構 HeroService:改用 HttpClient
將原先模擬的 Observable 改為 HTTP 請求。
// src/app/hero.service.ts
import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { tap } from 'rxjs';
export type Hero = { id: number; name: string; rank?: string };
@Injectable({
  providedIn: 'root',
})
export class HeroService {
  private readonly http = inject(HttpClient);
  private readonly baseUrl = 'api/heroes';
  private readonly cache = new Map<number, Hero>();
  getAll$() {
    return this.http.get<Hero[]>(this.baseUrl).pipe(
      tap((heroes) => {
        this.cache.clear();
        for (const hero of heroes) {
          this.cache.set(hero.id, hero);
        }
      })
    );
  }
  getById$(id: number) {
    return this.http.get<Hero>(`${this.baseUrl}/${id}`).pipe(
      tap((hero) => {
        if (!hero) {
          return;
        }
        this.cache.set(hero.id, hero);
      })
    );
  }
  updateName(id: number, name: string): Hero | undefined {
    const hero = this.cache.get(id);
    if (!hero) return undefined;
    const updated = { ...hero, name: name.trim() };
    this.cache.set(updated.id, updated);
    return updated;
  }
}
驗收清單:
/heroes 能看到由 HTTP 取得的英雄清單。 
/detail/:id,可顯示單筆資料。 
常見錯誤與排查:
HeroService 已改為走 HttpClient 的 getAll$() 與 getById$()。今日小結:
今天我們導入了 provideHttpClient(),用 in-memory 假後端讓專案順利切換到透過 HTTP 取得資料,並維持原有的 RxJS 與 UI 狀態管理。
明天會接著完成 CRUD ,讓專案有一條完整的資料作業流程。
參考資料: