Help needed to modify api.get of ionic-starter-super


#1

In the starter example there is this API function:

  get(endpoint: string, params?: any, options?: RequestOptions) {
    if (!options) {
      options = new RequestOptions();
    }

    // Support easy query params for GET requests
    if (params) {
      let p = new URLSearchParams();
      for (let k in params) {
        p.set(k, params[k]);
      }
      // Set the search field if we have params and don't already have
      // a search field set in options.
      options.search = !options.search && p || options.search;
    }

    return this.http.get(this.url + '/' + endpoint, options);
  }

I would like to add a header with a token that comes from storage, so I modified the api to:

get(endpoint: string, params?: any, options?: RequestOptions) {
    if (!options) {
      options = new RequestOptions();
    }

    if (!options.headers) {
      options.headers = new Headers();
    }

    this.storage.get("token").then((token) => {
      if (token) {
        options.headers.append('Token', token);
      }
    });

    // Support easy query params for GET requests
    if (params) {
      let p = new URLSearchParams();
      for (let k in params) {
        p.set(k, params[k]);
      }
      // Set the search field if we have params and don't already have
      // a search field set in options.
      options.search = !options.search && p || options.search;
    }

    return this.http.get(this.url + '/' + endpoint,  options );
  }

This does not work because getting the token from storage and the http get request are async. http get gets called without additional header.

I tried to modify the code to:

  get(endpoint: string, params?: any, options?: RequestOptions) {
    if (!options) {
      options = new RequestOptions();
    }

    if (!options.headers) {
      options.headers = new Headers();
    }

    return this.storage.get("token").then((token) => {
      if (token) {
        options.headers.append('Token', token);
      }

      // Support easy query params for GET requests
      if (params) {
        let p = new URLSearchParams();
        for (let k in params) {
          p.set(k, params[k]);
        }
        // Set the search field if we have params and don't already have
        // a search field set in options.
        options.search = !options.search && p || options.search;
      }

      return this.http.get(this.url + '/' + endpoint,  options )
    });
  }

But then i get following errors:

[18:24:05]  typescript: src/pages/item-detail/item-detail.ts, line: 51 
            Property 'share' does not exist on type 'Promise<Observable<Response>>'. 

      L50:  this.api.get('mobile/api/customerDetails', params, options)
      L51:  .share()
      L52:  .map(resp => resp.json())

[18:24:05]  typescript: src/providers/items.ts, line: 23 
            Property 'map' does not exist on type 'Promise<Observable<Response>>'. 

      L23:      return this.api.get('mobile/api/customerSearch', params, options).map(resp => resp.json());

My quesstion is: What to change, so that i can chain the promises (getting token from storage and then call http get) AND return the HttpPromise from the this.http.get call.


#2

What is this? Can you provide a link?


#3

Oh, are you talking about https://github.com/ionic-team/ionic-starter-super? Mentioning this wouldn’t be the worst idea…


#4

yes, this is what i meant. Sorry I forgot that I named the project different.

Its cloned from https://github.com/ionic-team/ionic-starter-super/

api class i’ve mentioned is: https://github.com/ionic-team/ionic-starter-super/blob/master/src/providers/api.ts


#5

So this.http.get doesn’t return a Promise, rather it returns an Observable. So what you’ll need to do is return an Observable from get.

Observables aren’t my strong suit, but I believe you’ll want something like this:

get(endpoint: string, params?: any, options?: RequestOptions) {
    if (!options) {
      options = new RequestOptions();
    }

    if (!options.headers) {
      options.headers = new Headers();
    }

    return Observable.fromPromise(this.storage.get("token")).flatMap(token => {
        if (token) {
            options.headers.append('Token', token);
        }

        // Support easy query params for GET requests
        if (params) {
            let p = new URLSearchParams();
            for (let k in params) {
                p.set(k, params[k]);
            }
            // Set the search field if we have params and don't already have
            // a search field set in options.
            options.search = !options.search && p || options.search;
        }

        return this.http.get(this.url + '/' + endpoint,  options );            
    });
}

#6

It is an important habit to declare return types of all functions. If you had done so, the compiler would have told you exactly what was wrong.