4

I'm trying to set a max timeout for HTTP requests with Angular5 and here's what I have based on what I found:

@Injectable()
export class TokenInterceptor implements HttpInterceptor {
  constructor(private tokenService:TokenService) {}
  /**
   * This method will add the Authorization header on each API request
   * @param request 
   * @param next 
   */
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    if (request.url.includes('/api/')) {
      request = request.clone({ setHeaders: { Authorization: 'Bearer ' + this.tokenService.getToken() } });
      return next.handle(request).timeout(1, Observable.throw("Request timed out"));
    }
    return next.handle(request);
  }
}

Except it says that timeout does not exist on type Observable<HttpEvent<any>>

How can I set the timeout for a request?

Shamoon
  • 41,293
  • 91
  • 306
  • 570

2 Answers2

3

Note: I havn't found a way to extend the timeout, but this will allow you to edit the timeout to shorter than the default of 2 minutes. If you are posting something to the backend that takes over 2 minutes to process you should alert the client that you have the data and are trying to process it instead of attempting to extend the timeout.

Here is how you would go about shortening a timeout:

Inside of your app module you should create the interceptor with a custom timeout in milliseconds.

import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { TimeoutError } from 'rxjs/util/TimeoutError';
import 'rxjs/add/operator/timeout';
import { InjectionToken, Injectable, Inject } from '@angular/core';
import { HttpHandler, HttpRequest, HttpInterceptor, HttpEvent } from '@angular/common/http';

const DEFAULT_TIMEOUT = new InjectionToken<number>('defaultTimeout');
const defaultTimeout = 5000;

@Injectable()
export class TimeoutInterceptor implements HttpInterceptor {
  constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout) { }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const timeout = Number(req.headers.get('timeout')) || this.defaultTimeout;
    return next.handle(req).timeout(timeout);
  }
}

Add this to your providers list:

[{ provide: HTTP_INTERCEPTORS, useClass: TimeoutInterceptor, multi: true }],
[{ provide: DEFAULT_TIMEOUT, useValue: defaultTimeout }]

When you make the request you want to add a custom header that uses your interceptor, it looks like this:

const options = {
    headers: new HttpHeaders({ timeout: `${3600000}` }),
    params: params,
    reportProgress: true,
    Timeout: 5000
};

Now when you make a request that hits the 5000 millisecond timeout it should stop.

TrystanHumann
  • 880
  • 8
  • 13
  • 2
    The problem is the `next.handle(req).timeout` function isn't defined – Shamoon Mar 29 '18 at 18:20
  • I made an edit to import HTTP_INTERCEPTORS from angular/common/http at the top, did you include that? – TrystanHumann Mar 29 '18 at 18:27
  • You could check for status code in the response header. This would be done in a section that looks like this : https://stackoverflow.com/questions/42104629/angular-2-checking-for-server-errors-from-subscribe – TrystanHumann Mar 29 '18 at 19:51
1

This answer can help you. It was said:

It appears that without extending HttpClientModule classes, the only expected ways for interceptors to communicate with respective requests are params and headers objects.

Since timeout value is scalar, it can be safely provided as a custom header to the interceptor, where it can be decided if it's default or specific timeout that should be applied via RxJS timeout operator:

const DEFAULT_TIMEOUT = new InjectionToken<number>('defaultTimeout');
const defaultTimeout = 10000;

@Injectable()
export class TimeoutInterceptor implements HttpInterceptor {
  constructor(@Inject(DEFAULT_TIMEOUT) protected defaultTimeout) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const timeout = Number(req.headers.get('timeout')) || this.defaultTimeout;
    return next.handle(req).timeout(timeout);
  }
}
Radonirina Maminiaina
  • 6,958
  • 4
  • 33
  • 60