Search code examples
javascriptangularpromiseobservableangular2-http

http call not triggering in promise callback angular 2


In my angular 2 project I make this call to get some data:

this.http.getfromgraphql()
      .map((response: Response) => response.json())
      .subscribe(
        (data) => {
          console.log(data);
        });

This triggers the getfromgraphql function shown below, before I make that call though, I have to check if the access token is still valid in checkaccesstokenvalidity, there I set some variables and resolve the function.
the console logs 'in then' but my http post does not trigger.
Why is that?
Also, I am sure there is a better way to do this, but for the life of me I can't figure it out, a better solution is much appreciated

checkAccessTokenValidity() {
    let headers = new Headers();
    headers.append( 'Content-Type', 'application/x-www-form-urlencoded' );
    let options = new RequestOptions({ headers: headers });
    // if(!this.access_token) {
    return new Promise((resolve, reject) => {
      this.http.post(this.URL + 'oauth/token', this.authentication, options)
        .subscribe(function(response) {
            this.authObj = response.json();
            this.expirationDate = new Date();
            this.expirationDate.setSeconds(this.expirationDate.getSeconds() + this.authObj.expires_in);
            console.log(this.authObj, this.expirationDate);
          },
          error => console.log("Error: ", error),
          function() {
            console.log('resolving');
            resolve();
          });

    });
    // }
  }
  getfromgraphql() {
    let headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    // headers.append('Authorization', 'Bearer ' + this.access_token );
    let options = new RequestOptions({ headers: headers });

    this.checkAccessTokenValidity().then(function() {
      console.log('in then');
      //noinspection TypeScriptValidateTypes
      return this.http.post(this.URL + '/api/v1/graphql', this.query, options);
    });
  }

Solution

  • Point 1:

    Do not use function(){} in any of your callbacks. Assuming you are using Typescript (or ES6 for that matter), you are not using lexical this. All of your this will have a reference to the inner scope. You will get lots of undefined. Use fat arrow notations ()=>{}.

    Point 2:

    Since you are already using Observables in all of your methods, continue to use them (reactive programming) and stay away from using Promise unless necessary.

    In your getfromgraphql() method, simply use a flatMap(). It is the same as .then() in promise.

    Also, in resolving the error, simply do a .catch() if needed. Observables will propagate the error to the highest caller.

    checkAccessTokenValidity() {
        let headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded');
        let options = new RequestOptions({headers: headers});
        return this.http.post(this.URL + 'oauth/token', this.authentication, options)
            .map(response => {
                this.authObj = response.json();
                this.expirationDate = new Date();
                this.expirationDate.setSeconds(this.expirationDate.getSeconds() + this.authObj.expires_in);
                console.log(this.authObj, this.expirationDate);
            })
            .catch(error=>{
                console.log(error);
                return Observable.empty();
            })
    }
    
    getfromgraphql() {
        let headers = new Headers();
        headers.append('Content-Type', 'application/x-www-form-urlencoded');
        // headers.append('Authorization', 'Bearer ' + this.access_token );
        let options = new RequestOptions({headers: headers});
    
        return this.checkAccessTokenValidity().flatMap(()=>{
            console.log('in then');
            //noinspection TypeScriptValidateTypes
            return this.http.post(this.URL + '/api/v1/graphql', this.query, options);
        })
    }