התפקיד של אינטרספטור הוא "לתפוס" כל קריאת HTTP לשרת ולבצע עליה שינוי ממש לפני השליחה, ניתן גם לשרשר מספר אינטרספטורים אחד אחרי השני אם יש צורך, כאשר כל אחד מבצע את השינויים שהוא צריך.
אחרי שכל השרשרת הסתיימה, הבקשה תשלח.
איפה זה פוגש אותנו?
אני אראה כאן 2 דוגמאות לאינטרספטורים שונים בעלי תפקיד גלובלי באפליקציה שלנו.
import { HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { AuthService } from "./auth.service";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) { }
intercept(req: HttpRequest<any>, next: HttpHandler) {
const authToken = this.authService.getToken();
const authRequst = req.clone({
headers: req.headers.set('Authorization', "Bearer " + authToken)
})
return next.handle(authRequst);
}
}מה הוא עושה?
הוא מוסיף נתונים של אימות משתמש לכל בקשה שנשלחת לשרת כדי שהשרת יוכל לאמת את המשתמש.
את נתוני האימות הטוקן, הוא לוקח מסרויס בשם AuthService שאנחנו בנינו ובשורה 11 הוא מוסיף header נוסף לבקשה (שימו לב שצריך לאפשר אותו בצד השרת).
הפרמטר הזה יחזיר את שם ה-header , שהוא Authorization ואת הערך שלו שמורכב מהמילה Bearer ואז רווח והמזהה של המשתמש.
כדי למנוע בעיות מול אנגולר , אנחנו מבצעים בשורה 10 שיכפול לבקשה עם התוספת ושולחים אותה במקום הבקשה המקורית.
בשורה 13 אנחנו מבצעים NEXT כדי לקדם את הבקשה הלאה.
זה יכול להיות לאינטרספטור אחר או לכיוון השרת אם אין עוד.
איך מפעילים אותו?
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
],providers נמצא מיד אחרי declarations ו-imports , אם הוא לא שם , אז אפשר פשוט להוסיף אותו.
דבר אחד נוסף וחשוב, את multi אנחנו מגדירים כ-true על מנת שהוא לא ישתמש באותו משתנה של הפונקציה אלא יצור אחד חדש בכל הפעלה של הפונקציה הזאת.
במילים אחרות, אם יהיו לי 5 בקשות בו זמנית לשרת, כל בקשה תקבל אינטרספטור נקי וחדש רק בשבילה.
נעבור לאינטרספטור השני
import { HttpErrorResponse, HttpHandler, HttpInterceptor, HttpRequest } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { MatDialog } from "@angular/material";
import { throwError } from "rxjs";
import { catchError } from "rxjs/operators";
import { ErrorComponent } from "./error/error.component";
@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
constructor(private dialog: MatDialog) { }
intercept(req: HttpRequest<any>, next: HttpHandler) {
return next.handle(req).pipe(
catchError((error: HttpErrorResponse) => {
let errorMessage = "An unknown error accurred!!";
if (error.error.message) {
errorMessage = error.error.message;
}
this.dialog.open(ErrorComponent, { data: { message: errorMessage } });
return throwError(error)
})
);
}
}זה אינטרספטור שאחראי על הפניה או "תפיסה" של שגיאה שחוזרת מהשרת לכיוון רכיב שידע להציג את הודעת השגיאה בפופאפ למשתמש.
במקרה הזה אין צורך לבצע שיכפול של הבקשה מהסיבה שאנחנו לא משנים אותה אלא רק מושכים ממנה מידע במידה שהיתה שגיאה.
זה אומר שאם הסטטוס שחוזר מהשרת מראה שגיאה (401,500,501 וכו') האינטרספטור יחפש את error.message, זה מידע שאנחנו צריכים לשלוח מהשרת כאובייקט.
והוא יעביר את המידע במקרה הזה לרכיב של אנגולר מטריאל שהוא דיאלוג, במידה שהשרת לא החזיר הודעת שגיאה, אז יש איתחול להודעה כללית שאומרת An unknown error accurred.
ולבסוף אנחנו מחזירים את השגיאה כ-observable, על ידי שימוש ב-throwError.
נפעיל את 2 האינטרספטורים
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
],כפי שאפשר לראות, הם מופעלים אוטומטית ואין צורך להפעיל אותם בכל מקום ופונקציה באפליקציה בנפרד.





