您的位置:首页 > Web前端 > AngularJS

在Angular软件中执行API请求的正确方式,了解一下

2020-04-02 07:18 1021 查看

全文共5358字,预计学习时长16分钟

 

来源:Pexels

 

本文将讨论如何在Angular应用程序中执行请求。

 

1. 使用拦截器来装饰请求

2. HttpClient 与HttpBackend的对比

3. 其他方式

 

这篇文章建立在我多年进行前端工作的经验(4年Angular工作经验)上。如有错误之处,请不吝赐教。

 

使用拦截器来装饰请求

 

使用API(应用程序接口)工作时, HTTP拦截器是一项主要特征。通过拦截,您使用拦截器,以检查HTTP请求并将其从应用程序发送到服务器,并从服务器返回应用程序的响应中进行转换。

 

简单来说:

在实际操作中,用户登录后,每个向后端传输的API都需要在标头添加授权,以核实用户的身份及授权。

 

例1:使用拦截器向请求添加JWT

[code] 
[code]@Injectable()
exportclass  RequestInterceptorService implements HttpInterceptor{
constructor(private store: Store)  { }
intercept(
request: HttpRequest<any>, next:  HttpHandler
): Observable<any> {
const userInfo = this.store.selectSnapshot<User>(state  => state.AppState.user);
const authReq = request.clone({
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Bearer ${userInfo.token}`
})
});
return next.handle(authReq);
}
}

 

使用拦截器向请求添加jwt

 

例2: 使用拦截器控制应用程序上的微调器

[code] 
[code]@Injectable({
providedIn: 'root'
})
exportclass  LoadingInterceptorService {
activeRequests: number =0;
constructor(
private  loadingScreenService: LoadingService
) { }
intercept(request: HttpRequest<any>,  next: HttpHandler): Observable<HttpEvent<any>> {
if (this.activeRequests===0) {
this.loadingScreenService.startLoading();
}
this.activeRequests++;
return next.handle(request).pipe(
finalize(() => {
this.activeRequests--;
if (this.activeRequests===0) {
this.loadingScreenService.stopLoading();
}
})
)
};
}

 

使用拦截器控制应用程序上的微调器

 

例 3: 使用拦截器来高速缓存请求

[code] 
[code]@Injectable()
exportclass  CachingInterceptor implements HttpInterceptor {
constructor(private cache:  RequestCache) {}
intercept(req: HttpRequest<any>,  next: HttpHandler) {
// continue if not cachable.
if (!isCachable(req)) { return next.handle(req); }
const cachedResponse = this.cache.get(req);
return cachedResponse ?
of(cachedResponse)  : sendRequest(req, next, this.cache);
}
}

 

使用拦截器来高速缓存请求

 

也可以做更多与请求有关的事情:

 

· 在API失败的情况下显示模型。

· 响应后根据状态代码添加更多操作规则

· 覆盖URL请求或请求正文

 

拦截器将影响您的所有请求。那么,如何在Angular中自定义请求并禁用拦截器呢?下面来一起看看

 

HttpClient与HttpBackend的对比

 

我观察到很多开发人员仅在他们需要向后端发送请求时,才在Angular项目中使用HttpClient。而这是不正确的。

 

为什么?

 

来源:Pexels

 

因为我们由HttpClient发送的请求总是经过Angular的拦截器。为了解决这个问题,一些开发人员编写更多代码以禁用拦截器,我称之为“作弊代码”。而一些开发人员并不会使用拦截器来处理请求,并向每个请求添加标头。

 

这使代码充满代码异味和技术债务。开发人员必须使用上述两个选项之一来完成更多的工作。

 

解决办法: 使用 HttpClient 和HttpBackend 来发送请求。

 

唯一不同之处在于 HttpBackend 将请求直接发送到后端,而不经过拦截器链。

 

HttpService样本:

[code] 
[code]import { Injectable  } from'@angular/core';
import {  HttpHeaders, HttpClient, HttpParams, HttpBackend } from'@angular/common/http';
import { Observable,  throwError, of } from'rxjs';
import { catchError  } from'rxjs/operators';
@Injectable({
providedIn: 'root'
})
exportclass HttpService {
privatehttpWithoutInterceptor: HttpClient;
constructor(
private http:  HttpClient,
private httpBackend:  HttpBackend
) {
this.httpWithoutInterceptor=new HttpClient(httpBackend);
}
privateformatErrors(error: any) {
returnthrowError(error.error);
}
get(path: string,  params: HttpParams =new  HttpParams()): Observable<any> {
return this.http.get(`${path}`, { params })
.pipe(catchError(this.formatErrors));
}
put(path: string,  body: Object = {}): Observable<any> {
return this.http.put(
`${path}`,
JSON.stringify(body)
).pipe(catchError(this.formatErrors));
}
post(path: string,  body: Object = {}, options: Object = {}):  Observable<any> {
return this.http.post(
`${path}`,
JSON.stringify(body),
options
).pipe(catchError(this.formatErrors));
}
delete(path): Observable<any>  {
return this.http.delete(
`${path}`
).pipe(catchError(this.formatErrors));
}
_get(path: string,  params: HttpParams =new  HttpParams()): Observable<any> {
return this.httpWithoutInterceptor.get(`${path}`, { params })
.pipe(catchError(this.formatErrors));
}
_put(path: string,  body: Object = {}): Observable<any> {
return this.httpWithoutInterceptor.put(
`${path}`,
JSON.stringify(body)
).pipe(catchError(this.formatErrors));
}
_post(path: string,  body: Object = {}, options: Object = {}):  Observable<any> {
return this.httpWithoutInterceptor.post(
`${path}`,
JSON.stringify(body),
options
).pipe(catchError(this.formatErrors));
}
_delete(path):  Observable<any> {
return this.httpWithoutInterceptor.delete(
`${path}`
).pipe(catchError(this.formatErrors));
}
}

 

view rawhttp.service.ts hosted with ❤ by GitHub

 

使用httpclient和httpbackend的httpservice样本

 

您将做出决定,哪种方式经过拦截器,哪种方式不经过。

 

对于一些特定的API(应用程序接口)需要不同的标头或添加其他信息,才可以使用 HttpBackend来手动对其进行自定义。

 

其他方式

 

我以此作为标题是因为下面是一些您可能遇到过或没有遇到过的小用例。

 

失败后如何调用API?

[code] 
[code]getConfig() {
return this.http.get<Config>(this.configUrl)
.pipe(
retry(3), // retry a  failed request up to 3 times
);
}

 

重试失败的请求,最多三次

 

如果请求失败,使用retry()(异常重试)来延长尝试该请求的时间。

 

如何捕捉错误?

 

建议使用next()函数捕捉拦截器的错误。

[code] 
[code]@Injectable()
exportclass  ErrorInterceptorService implements HttpInterceptor  {
constructor() { }
intercept(
request: HttpRequest<any>, next:  HttpHandler
): Observable<any> {
return next.handle(request).pipe(
catchError(this.handleError)
);
}
privatehandleError(error:  HttpErrorResponse) {
if (error.errorinstanceof ErrorEvent) {
console.error('An error  occurred:', error.error.message);
} else {
console.error(
`Backend returned  code ${error.status}, `+
`body was: ${error.error}`);
}
returnthrowError(
'Something bad  happened; please try again later.');
};
}

 

如何避免 XSRF攻击?

 

执行HTTP 请求时, 拦截器从cookie读取令牌,默认为XSRF-TOKEN,并将其设置为 HTTP 标头, X-XSRF-TOKEN。由于只有在您的域上运行的代码才能读取cookie,因此后端可以确定HTTP请求来自您的客户端应用程序而不是攻击者。

 

如果后端服务对XSRF令牌cookie或标头使用不同的名称,则使用HttpClientXsrfModule.withOptions() 来覆盖。

[code] 
[code]imports: [
HttpClientModule,
HttpClientXsrfModule.withOptions({
cookieName: 'My-Xsrf-Cookie',
headerName: 'My-Xsrf-Header',
}),
],

 

使用HttpClientXsrfModule 覆盖 XSRF令牌

 

来源:Pexels

 

本文包含了所有使用Angular应用程序的API时的必要信息,包括:

 

· 使用拦截器来管理请求和响应

· 如何使用HttpClient和HttpBackend

· 请求失败后,如何重新调回,如何捕捉错误和避免XSRF攻击。

 

希望此文章对您有帮助!

留言 点赞 关注

我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”

(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)

  • 点赞
  • 收藏
  • 分享
  • 文章举报
读芯术 发布了961 篇原创文章 · 获赞 2915 · 访问量 61万+ 他的留言板 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐