0

Angular Chain Http Request

I created a service where I wrapped all my HTTP requests (get, put, post...).

get(url) {
 const headers = new Headers();
 this.sessionToken(headers); // just add the headers...
 return this.http.get(url, {
   headers: headers
 });
}

How can I perform a method before the (eg.) GET request is sent?

In my scenario, I have a method that returns me back a token and this token need to be saved on the localStorage and, following the chain, appended to the headers!

initClient() {
 return this.http.post('/connect/', {})
   .map(res => res.json())
}

How can I conditionally insert this request before the Http call is done?

Directly in this Service and not going to subscribe on each HTTP calls.

Here what I tried to do:

get(url) {
 if (!localStorage.getItem('token')) {
  this.initClient()
    .subscribe(session => {
      localStorage.setItem('token', JSON.stringify(session));
    });
 }
const headers = new Headers();
this.sessionToken(headers);
 return this.http.get(url, {
  headers: headers
 });
}

But the HTTP request is solved before of the initClient() is called!

What I need to do?

  1. A method returns an Http request
  2. Before the request is sent Get Token / Set Token localStorage
  3. Continue Http request including the Token in the Headers

Possible Solution - Error:
@CozyAzure - Answer enter image description here
Argument of type '(session: any) => void' is not assignable to parameter of type '(value: any, index: number) => ObservableInput<{}>'. Type 'void' is not assignable to type 'ObservableInput<{}>'.

Trying to set initClient() { ...} to be of type "any":
initClient(): any { ... } the previous error disappear, but another error comes out:
ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

Leniel Maccaferri
  • 100,159
  • 46
  • 371
  • 480
39ro
  • 862
  • 1
  • 10
  • 23
  • How about `flatMap` (`mergeMap`): https://stackoverflow.com/questions/34104638/how-to-chain-http-calls-in-angular2 – AT82 Jul 12 '17 at 18:56

1 Answers1

1

What you need is Observable.flatMap(). flatMap() acts just like .then() in Promise.

Also, specific to your question, you can get some help from Observable.if() to make your code looks cleaner. Observable.if(condition, thenSource, [elseSource]) takes in 3 arguments. First argument is the boolean condition, second argument is an Observable to be emitted if condition is true, and the last one being an array of else source, that is to be emmitted if condition is false.

Something like this:

get(url) {
    return Observable
        .if(
        //a function that returns a boolean
        () => !localStorage.getItem('token'),
        //an Observable to return if condition is true
        this.initClient()
            //use flatMap to proceed to next Observable
            .flatMap(session => {
                return localStorage.setItem('token', JSON.stringify(session));
            }),
        //an Observable to return if condition is false
        //return dummy value so that Observable can continue
        Observable.of('')
        )
        .flatMap(() => {
            const headers = new Headers();
            this.sessionToken(headers);
            return this.http.get(url, {
                headers: headers
            });
        })
}

And now you can call get(url) in your component:

this.myService.get(API_URL)
    .subscribe(response => {
        console.log(response)
    });
CozyAzure
  • 8,280
  • 7
  • 34
  • 52
  • I was trying to find a solution for it, but not able to find it! The Observable looks to be stopped by this error: *ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.* I set **initClient()** to be type of _"any"_ instead the flatMap of **initClient()** start to complain: *Type 'void' is not assignable to type 'ObservableInput<{}>'.* – 39ro Jul 13 '17 at 10:13
  • I forgot to say that at the next refresh the call is made and I get the data! What do you think is going on? – 39ro Jul 13 '17 at 10:50
  • @39ro high chance your browser is caching the old code! – CozyAzure Jul 13 '17 at 10:59
  • really thanks for your code, It's an Observable error my browser looks to be with me! :D I restarted Angular CLI and I also clean the localStorage! – 39ro Jul 13 '17 at 11:05
  • @39ro You can mark as answer if it solves your issue. – CozyAzure Jul 13 '17 at 11:16