面试题答案
一键面试请求方法选择
- GET:用于获取数据,幂等且可缓存。适用于查询操作,例如获取用户信息。
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class UserService { constructor(private http: HttpClient) {} getUser(id: number) { return this.http.get(`api/users/${id}`); } }
- POST:用于创建新资源,非幂等且不可缓存。适用于提交表单等操作,如注册新用户。
@Injectable({ providedIn: 'root' }) export class AuthService { constructor(private http: HttpClient) {} registerUser(userData: any) { return this.http.post('api/register', userData); } }
参数传递优化
- URL参数:简单参数可放在URL中,适用于GET请求。
@Injectable({ providedIn: 'root' }) export class ProductService { constructor(private http: HttpClient) {} getProductsByCategory(category: string) { return this.http.get(`api/products?category=${category}`); } }
- 请求体:复杂数据结构使用请求体,适用于POST、PUT等请求。
@Injectable({ providedIn: 'root' }) export class OrderService { constructor(private http: HttpClient) {} placeOrder(orderData: any) { return this.http.post('api/orders', orderData); } }
缓存机制
- 客户端缓存:使用RxJS的
shareReplay
操作符实现简单缓存。import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable, shareReplay } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class DataService { private cachedData$: Observable<any>; constructor(private http: HttpClient) {} getData() { if (!this.cachedData$) { this.cachedData$ = this.http.get('api/data').pipe( shareReplay(1) ); } return this.cachedData$; } }
HTTP拦截器
- 统一处理请求参数:添加通用请求头。
import { Injectable } from '@angular/core'; import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept( request: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { const token = localStorage.getItem('token'); if (token) { request = request.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); } return next.handle(request); } }
- 统一处理响应数据:处理错误响应。
import { Injectable } from '@angular/core'; import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http'; import { Observable, catchError, tap } from 'rxjs'; import { ToastrService } from 'ngx-toastr'; @Injectable() export class ErrorInterceptor implements HttpInterceptor { constructor(private toastr: ToastrService) {} intercept( request: HttpRequest<any>, next: HttpHandler ): Observable<HttpEvent<any>> { return next.handle(request).pipe( tap((event: HttpEvent<any>) => { if (event instanceof HttpResponse) { // 可在此处理成功响应 } }), catchError((error) => { if (error.status === 401) { this.toastr.error('请重新登录', '未授权'); } else if (error.status === 500) { this.toastr.error('服务器错误', '系统故障'); } throw error; }) ); } }
架构设计思路
- 模块划分:将HTTP请求相关逻辑封装到服务中,如
UserService
、ProductService
等,提高代码可维护性。 - 拦截器配置:在
app.module.ts
中配置拦截器,确保所有HTTP请求都经过处理。import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform - browser'; import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; import { AppComponent } from './app.component'; import { AuthInterceptor } from './auth.interceptor'; import { ErrorInterceptor } from './error.interceptor'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, HttpClientModule], providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true } ], bootstrap: [AppComponent] }) export class AppModule {}
- 缓存管理:对于不同类型的数据,根据其更新频率和重要性,选择合适的缓存策略,如客户端缓存、服务器端缓存等。
- 异常处理:通过拦截器统一处理异常,向用户提供友好的提示信息,同时记录错误日志以便排查问题。