2

Common Task: I want to fetch data via HTTP only once and then make it accessible to my whole app as properties. But of course my app needs to "listen" to the properties, because HTTP is slow. I only want to call HTTP once (1 time) overall in the entire app.

@Injectable()
export class EnvService {

  imageTag: String;


  envData: Observable<any>;


  constructor(protected authHttp: AuthHttp) {

    let envSubscription = this.getConfig().subscribe(envConfig => {

      this.imageTag = envConfig.imageTag;

      this.envData = {
          'imageTag' : envConfig.imageTag,
      }

      envSubscription.unsubscribe();
    });

  }


  getData(): Observable<any> {

    return this.envData;

  }

  getConfig(): Observable<any> {

    const requestOptionsArgs: RequestOptionsArgs = {
      url: '/assets/env/env.json',
      method: RequestMethod.Get
    };

    const requestOptions: RequestOptions = new RequestOptions(requestOptionsArgs);
    return this.authHttp.request(new Request(requestOptions)).map(returnedEnvConfig => {

      return {
        imageTag: returnedEnvConfig.json().imageTag,
      };
    });
  }
}

imageTag: any is not assignable to type Observable

Any ideas how to do this?

1
  • is that helpful ?? updated my answer Commented Apr 16, 2018 at 13:20

3 Answers 3

1

You could achieve your goal by simply using the rxjs share operator.

By default, the Observable returned by the HttpClient will do a new call for every subscription. By adding a pipe(share()), you can change the behavior and share the response between all the subscribers.

Here is a stackblitz demonstration for the two cases. A line is added in the console for every performed http call.

Sign up to request clarification or add additional context in comments.

Comments

0

you can just do this , store data in localstorage once request get completed , so next time when you call it will return data from localstorage without going to server.

  getConfig(): Observable<any> {

    if( this.localStorage.get('key'));
      return of(this.localStorage.get('key'));
   else {

    const requestOptionsArgs: RequestOptionsArgs = {
      url: '/assets/env/env.json',
      method: RequestMethod.Get
    };

    const requestOptions: RequestOptions = new RequestOptions(requestOptionsArgs);
    return this.authHttp.request(new Request(requestOptions)).map(returnedEnvConfig => {
      localStorage.setItem("key",returnedEnvConfig.json().imageTag);
      return  returnedEnvConfig.json().imageTag;
    });
  }
 }

you just do like this

return this.authHttp.request(new 
      Request(requestOptions)).map(returnedEnvConfig => 
       returnedEnvConfig.json().imageTag);

it should be like

return this.authHttp.request(new Request(requestOptions));

if you want to return overservable , and where you subscribe do the operation which you are currently doing.

3 Comments

Sorry that is not helping.
How to connect envData: Observable<any>; and imageTag and the subscriber of the service? HTTP should be completely decoupled.
@nottinhill - if you want to call once only then susggest store data in localstorage after first request done, kind of cache data , thats what i do in my application
0

Use publishReplay(1).refCount(); to cache the operation.

 getConfig(): Observable<any> {

    const requestOptionsArgs: RequestOptionsArgs = {
      url: '/assets/env/env.json',
      method: RequestMethod.Get
    };

    const requestOptions: RequestOptions = new RequestOptions(requestOptionsArgs);
    return this.authHttp.request(new Request(requestOptions)).map(returnedEnvConfig => {

      return {
        imageTag: returnedEnvConfig.json().imageTag,
      };
    }).publishReplay(1).refCount();
  }

Read more: https://blog.angularindepth.com/rxjs-how-to-use-refcount-73a0c6619a4e

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.