默认和特定请求超时
Default and specific request timeout
通常需要默认超时(例如 30 秒),它将应用于所有请求,并且可以针对特定的 更长 请求(例如 600 秒)被覆盖。
据我所知,在 Http
服务中没有指定默认超时的好方法。
在 HttpClient
服务中解决这个问题的方法是什么?如何为所有传出请求定义默认超时,可以为特定请求覆盖?
使用新的 HttpClient,您可以尝试这样的事情
@Injectable()
export class AngularInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).timeout(5000).do(event => {}, err => { // timeout of 5000 ms
if(err instanceof HttpErrorResponse){
console.log("Error Caught By Interceptor");
//Observable.throw(err);
}
});
}
}
为传递的 next.handle(req)
添加超时。
像
一样在AppModule中注册它
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
[ { provide: HTTP_INTERCEPTORS, useClass:
AngularInterceptor, multi: true } ]
],
bootstrap: [AppComponent]
})
export class AppModule {
}
您可以使用如下基本超时值创建一个全局拦截器:
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
@Injectable()
export class AngularInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).timeout(30000, Observable.throw("Request timed out"));
// 30000 (30s) would be the global default for example
}
}
之后你需要在你的根模块的providers数组中注册这个injectable。
棘手的部分是覆盖特定请求的默认时间 (increase/decrease)。目前我不知道如何解决这个问题。
似乎在不扩展 HttpClientModule
类 的情况下,拦截器与相应请求通信的唯一预期方式是 params
和 headers
objects。
由于超时值是标量,它可以作为自定义 header 安全地提供给拦截器,在这里可以决定它是默认的还是应该通过 RxJS 应用的特定超时 timeout
运算符:
import { Inject, Injectable, InjectionToken } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
import { timeout } from 'rxjs/operators';
export const DEFAULT_TIMEOUT = new InjectionToken<number>('defaultTimeout');
@Injectable()
export class TimeoutInterceptor implements HttpInterceptor {
constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout: number) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const timeoutValue = req.headers.get('timeout') || this.defaultTimeout;
const timeoutValueNumeric = Number(timeoutValue);
return next.handle(req).pipe(timeout(timeoutValueNumeric));
}
}
这可以在您的应用模块中配置,例如:
providers: [
[{ provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true }],
[{ provide: DEFAULT_TIMEOUT, useValue: 30000 }]
],
然后使用自定义 timeout
header
完成请求
http.get('/your/url/here', { headers: new HttpHeaders({ timeout: `${20000}` }) });
由于header应该是字符串,所以应该先将超时值转换为字符串。
这里是a demo.
鸣谢@RahulSingh 和@Jota.Toledo,他们提出了将拦截器与 timeout
.
一起使用的想法
作为对其他答案的补充,请注意如果您在开发机器上使用 proxy config,代理的默认超时为 120 秒(2 分钟)。对于更长的请求,您需要在配置中定义更高的值,否则这些答案中的 none 将起作用。
{
"/api": {
"target": "http://localhost:3000",
"secure": false,
"timeout": 360000
}
}
通常需要默认超时(例如 30 秒),它将应用于所有请求,并且可以针对特定的 更长 请求(例如 600 秒)被覆盖。
据我所知,在 Http
服务中没有指定默认超时的好方法。
在 HttpClient
服务中解决这个问题的方法是什么?如何为所有传出请求定义默认超时,可以为特定请求覆盖?
使用新的 HttpClient,您可以尝试这样的事情
@Injectable()
export class AngularInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).timeout(5000).do(event => {}, err => { // timeout of 5000 ms
if(err instanceof HttpErrorResponse){
console.log("Error Caught By Interceptor");
//Observable.throw(err);
}
});
}
}
为传递的 next.handle(req)
添加超时。
像
一样在AppModule中注册它@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
HttpClientModule
],
providers: [
[ { provide: HTTP_INTERCEPTORS, useClass:
AngularInterceptor, multi: true } ]
],
bootstrap: [AppComponent]
})
export class AppModule {
}
您可以使用如下基本超时值创建一个全局拦截器:
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from '@angular/common/http';
@Injectable()
export class AngularInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).timeout(30000, Observable.throw("Request timed out"));
// 30000 (30s) would be the global default for example
}
}
之后你需要在你的根模块的providers数组中注册这个injectable。
棘手的部分是覆盖特定请求的默认时间 (increase/decrease)。目前我不知道如何解决这个问题。
似乎在不扩展 HttpClientModule
类 的情况下,拦截器与相应请求通信的唯一预期方式是 params
和 headers
objects。
由于超时值是标量,它可以作为自定义 header 安全地提供给拦截器,在这里可以决定它是默认的还是应该通过 RxJS 应用的特定超时 timeout
运算符:
import { Inject, Injectable, InjectionToken } from '@angular/core';
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
import { timeout } from 'rxjs/operators';
export const DEFAULT_TIMEOUT = new InjectionToken<number>('defaultTimeout');
@Injectable()
export class TimeoutInterceptor implements HttpInterceptor {
constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout: number) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const timeoutValue = req.headers.get('timeout') || this.defaultTimeout;
const timeoutValueNumeric = Number(timeoutValue);
return next.handle(req).pipe(timeout(timeoutValueNumeric));
}
}
这可以在您的应用模块中配置,例如:
providers: [
[{ provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true }],
[{ provide: DEFAULT_TIMEOUT, useValue: 30000 }]
],
然后使用自定义 timeout
header
http.get('/your/url/here', { headers: new HttpHeaders({ timeout: `${20000}` }) });
由于header应该是字符串,所以应该先将超时值转换为字符串。
这里是a demo.
鸣谢@RahulSingh 和@Jota.Toledo,他们提出了将拦截器与 timeout
.
作为对其他答案的补充,请注意如果您在开发机器上使用 proxy config,代理的默认超时为 120 秒(2 分钟)。对于更长的请求,您需要在配置中定义更高的值,否则这些答案中的 none 将起作用。
{
"/api": {
"target": "http://localhost:3000",
"secure": false,
"timeout": 360000
}
}