25

Here is just regular request looking like that:

this.people = http.get('http://localhost:3000/users')
                  .map(response => response.json());

Is there any way to delay/timeout that?

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
Sergino
  • 10,128
  • 30
  • 98
  • 159

4 Answers4

42

You can leverage the timeout operator of observables, as described below:

return this.http.get('http://api.geonames.org/postalCodeSearchJSON',
          { search: params })
    .retryWhen(error => error.delay(500))
    .timeout(2000, new Error('delay exceeded')) // <------
    .map(res => res.json().postalCodes);
Mike W
  • 425
  • 3
  • 12
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
  • 1
    I had to do: `.retryWhen(errors => errors.delayWhen(() => Observable.timer(1000)))` with rxjs 5.0.2. https://www.learnrxjs.io/operators/error_handling/retrywhen.html – Brandon Taylor Mar 14 '17 at 16:45
  • Is there a way to set the timeout globally? – Will May 05 '17 at 19:26
  • @Will Is there a way to set the timeout globally? – Joe Sleiman Jun 20 '17 at 10:11
  • @JoeSleiman you can set timeout globally by extending the `Http` class. See this article for more details: http://restlet.com/company/blog/2016/04/18/interacting-efficiently-with-a-restful-service-with-angular2-and-rxjs-part-3/ – Thierry Templier Jun 20 '17 at 13:19
  • @ThierryTemplier, can you take a look on this link : i describe my issue: https://stackoverflow.com/questions/44650013/add-header-and-timeout-request-globally – Joe Sleiman Jun 20 '17 at 13:31
  • was there any changes in doing that with a new `HttpClient` in `angular 4.3`? – Sergino Aug 11 '17 at 00:16
12

The return value of http.get() is an observable, not the response. You can use it like:

getPeople() {
  return http.get('http://localhost:3000/users')
      .timeout(2000)
      .map(response => response.json());
  }
}

foo() {
  this.subscription = getPeople.subscribe(data => this.people = data)
}

// to cancel manually
cancel() {
  this.subscription.unsubscribe();
}

See also https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/timeout.md

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 5
    Excellent answer - just a note: you also need to import the timeout operator from rxjs or this wont work: import 'rxjs/add/operator/timeout'; – rhysclay Feb 28 '17 at 22:36
  • Hi Gunter, I have used `timeout` with no effect (meaning no delay), but when I use `delay(1000)` it works with the data being delayed for 1 sec. I have imported ` 'rxjs/add/operator/timeout'` but even when I put `timeout(5000)` I get the data immediately. Does timeout do something different than to just delay the data? – Alfa Bravo Mar 16 '17 at 06:51
  • 1
    Timeout completes the observable with an error when the data doesn't arrive within time. Delay delays the output of events. – Günter Zöchbauer Mar 16 '17 at 06:53
  • How does unsubscribing from the observable cancel the http request? I don't think it does – LukeStoneHm Apr 07 '17 at 10:07
  • `http.xxx()` only emits one event and then completes. There is no need to unsubscribe. You only need to unsubscribe if the observable emits an endless stream of events. – Günter Zöchbauer Apr 07 '17 at 10:09
  • 1
    this should be `getPeople.subscribe(data => this.people = data)`, notice the fat arrow: `=>` – vs4vijay Jun 08 '17 at 14:24
  • @GünterZöchbauer Is there a way to set the timeout globally? – Joe Sleiman Jun 20 '17 at 10:12
  • You can build a custom `Http` class that extends `Http` and add custom code. AFAIK there is also a new `Http` implementation work in progress that seems to address such use cases, but I don't know details about the progress. – Günter Zöchbauer Jun 20 '17 at 12:00
  • @rhysclay with angular5 using HttpClient for me it works even without importing the timeout operator – tom Jan 09 '18 at 05:36
5

If you are using RxJS version 6 and above the current syntax is this:

import { timeout } from 'rxjs/operators';

getPeople(){
  return this.http.get(API_URL)
  .pipe(
      timeout(5000) //5 seconds
  );
Virendra Singh
  • 297
  • 3
  • 9
0

As with the new version, you must pipe to use the timeout. And to get the response you can use map inside. The complete code is as below.

import { map, timeout, catchError } from 'rxjs/operators';

const sub: any = this.httpClient.post(this.baseUrl, body)
    .pipe(timeout(Config.SesamTimeout),
        catchError((err: any) => {
            this.handleTimeout(err);
            return of(null);
        }),
        map((v: SesamResponse) => {
            if (v) {
                const a: SearchResultGroup[] = this.convertSesamResponseToApiFileItem(v);
                return a;
            }
        }));

Here Config.SesamTimeout is the time in milliseconds.

Sibeesh Venu
  • 18,755
  • 12
  • 103
  • 140