Тайм-аут по умолчанию и определенный запрос

Обычно желательно иметь время ожидания по умолчанию (например, 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
  }
}