จัดการ HTTP Response ใน Angular

Oct. 26, 2024 · boychawin

การจัดการข้อมูลที่ได้รับจาก API ด้วย HttpResponseInterceptor ช่วยให้เราสามารถปรับแต่งข้อมูล response ก่อนส่งไปยัง component ได้อย่างง่ายดาย หาก API ที่เราใช้งานส่งข้อมูลในโครงสร้างที่มีฟิลด์ data ห่อหุ้มข้อมูลที่เราต้องการ เช่น

{
  "data": {
    "id": 1,
    "title": "Example Title",
    "content": "This is an example post."
  }
}

อธิบายโค้ด

HttpResponseInterceptor จะดักจับทุก response ที่มาจาก API และจะตรวจสอบว่าข้อมูล response ที่มีฟิลด์ data อยู่หรือไม่

  • ถ้ามี data ใน response จะดึงข้อมูลเฉพาะที่อยู่ใน data และส่งต่อไปยัง component
  • ถ้าไม่มี data ก็จะส่ง response ทั้งหมดไปยัง component โดยไม่ปรับแต่ง

ด้วยวิธีนี้ เราจะได้ข้อมูลที่ต้องการโดยไม่ต้องเขียนโค้ดซ้ำๆ ในทุก component ที่เรียกใช้ API

ตัวอย่างการใช้งาน

เริ่มต้นด้วยการสร้างไฟล์ Interceptor ในโฟลเดอร์ shared/interceptor/ และตั้งชื่อว่า http-response.interceptor.ts โดยใส่โค้ดดังนี้

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpResponse
} from '@angular/common/http';
import { map, Observable } from 'rxjs';

@Injectable()
export class HttpResponseInterceptor implements HttpInterceptor {

  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request).pipe(
      map((response) => {
        if (response instanceof HttpResponse) {
          // ตรวจสอบว่ามีฟิลด์ data ใน body หรือไม่
          if (response.body && response.body.hasOwnProperty('data')) {
            response = response.clone({ body: response.body.data });
          }
        }
        return response;
      })
    );
  }
}

การเพิ่ม Interceptor ใน AppModule

ใน app.module.ts ให้ทำการนำเข้า Interceptor และเพิ่มเข้าไปใน providers เพื่อให้ Angular ใช้งาน Interceptor กับทุกๆ request/response

import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { HttpResponseInterceptor } from './shared/interceptor/http-response.interceptor';

@NgModule({
  imports: [
    HttpClientModule,
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpResponseInterceptor,
      multi: true,
    },
  ],
})
export class AppModule {}

ทดสอบ Interceptor ใน Component

สร้าง component สำหรับทดสอบการทำงานของ HttpResponseInterceptor และเรียก API ที่ไม่มีฟิลด์ data เพื่อตรวจสอบว่า Interceptor ทำงานได้อย่างถูกต้อง โดยใช้โค้ดดังนี้

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

@Component({
  selector: 'app-test-interceptor',
  template: `<button (click)="fetchData()">Fetch Data</button><pre>{{ apiResponse | json }}</pre>`,
})
export class TestInterceptorComponent {
  apiResponse: any;

  constructor(private http: HttpClient) {}

  fetchData() {
    this.http.get('https://jsonplaceholder.typicode.com/posts').subscribe({
      next: (data) => this.apiResponse = data,
      error: (err) => console.log('Error caught in component:', err),
    });
  }
}

สรุป

HttpResponseInterceptor ช่วยลดขั้นตอนและโค้ดที่ซ้ำซ้อนในการดึงข้อมูล API ให้เราไม่ต้องมาจัดการโครงสร้าง response ใน component หลายๆ ที่ ซึ่งช่วยให้โค้ดสะอาดและดูแลง่ายมากขึ้น เหมาะสำหรับใครที่ต้องการควบคุมข้อมูล response จาก API ในแอปพลิเคชันแบบง่ายๆ