Тайм-аут по умолчанию и определенный запрос
Обычно желательно иметь время ожидания по умолчанию (например, 30 с), которое будет применяться ко всем запросам и может быть переопределено для конкретных более длинных запросов (например, 600 с).
Насколько мне известно, нет хорошего способа указать время ожидания по умолчанию в службе Http
.
Как это можно сделать в сервисе HttpClient
? Как определить время ожидания по умолчанию для всех исходящих запросов, которое можно переопределить для определенных?
Ответы
Ответ 1
Похоже, что без расширения классов HttpClientModule
единственными ожидаемыми способами взаимодействия перехватчиков с соответствующими запросами являются объекты params
и headers
.
Поскольку значение тайм-аута является скалярным, его можно безопасно предоставить в качестве настраиваемого заголовка перехватчику, где можно решить, будет ли это значение по умолчанию или определенный тайм-аут, который следует применять с помощью оператора 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(timoutValue);
return next.handle(req).pipe(timeout(timeoutValueNumeric));
}
}
Это можно настроить в вашем модуле приложения, например:
...
providers: [
[{ provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true }],
[{ provide: DEFAULT_TIMEOUT, useValue: 30000 }]
],
...
Затем запрос выполняется с помощью пользовательского заголовка timeout
http.get(..., { headers: new HttpHeaders({ timeout: '${20000}' }) });
Так как заголовки должны быть строками, значение времени ожидания должно быть сначала преобразовано в строку.
Вот демо.
Авторы обращаются к @RahulSingh и @Jota.Toledo за предложение об использовании перехватчиков с timeout
.
Ответ 2
Используя новый 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 {
}
Ответ 3
Вы можете создать глобальный перехватчик с базовым значением таймаута следующим образом:
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
}
}
Затем вам необходимо зарегистрировать эту инъекцию в массиве поставщиков корневого модуля.
Сложной частью было бы переопределить время по умолчанию (увеличение/уменьшение) для конкретных запросов. На данный момент я не знаю, как это решить.
Ответ 4
В дополнение к другим ответам, просто имейте в виду, что если вы используете прокси-конфигурацию на компьютере разработчика, время ожидания прокси-сервера по умолчанию составляет 120 секунд (2 минуты). Для более длинных запросов вам нужно будет указать более высокое значение в конфигурации, иначе ни один из этих ответов не будет работать.
{
"/api": {
"target": "http://localhost:3000",
"secure": false,
"timeout": 360000
}
}