Arnaud H
Arnaud H

Reputation: 1011

Mitigate multiple http request in Angular2 Service

I am trying to share the result of an http request from the following service with multiple components. The problem I am experiencing, is that each component's request for the getMe() function creates a new http call. The MeService service is only declared as a provider in the root module of the page, and imported in each *.component.ts, so this is not caused by the (common) mistake of redeclaring the service multiple times as a provider in all child components. As you'll be able to tell from the output, it is most likely caused due to the async nature of the call, but correct me if I'm wrong.

Here is the service code:

import { Injectable } from '@angular/core';
import { Headers, Http } from '@angular/http';

import 'rxjs/add/operator/toPromise';

@Injectable()
export class MeService {

    private apiUrl = 'api/get/me';

    private me: Object;

    constructor(private http: Http) { }

    getMe(): Promise<Object> {

        console.log("OBSERVATION 1: " + this.me);

        if (this.me) {

            //Not sure if this is correct or not, I've never reached this block yet
            return Promise.resolve(this.me)

        } else {

            return this.http.get(this.apiUrl)
                .toPromise()
                .then(response => {

                    console.log("OBSERVATION 2: " + this.me);

                    this.me = response.json();

                    console.log("OBSERVATION 3: " + this.me);

                    return this.me
                })
                .catch(this.handleError);

        }
    }

    //Not relevant, just for completeness
    private handleError(error: any): Promise<any> {

        console.error('An error occurred', error); // for demo purposes only
        return Promise.reject(error.message || error);

    }
}

The output in the console. Mind that the [object Object] are filled with the correct data, I have checked this and omitted the JSON.Stringify() for clarity.

OBSERVATION 1: undefined

OBSERVATION 1: undefined

OBSERVATION 2: undefined

OBSERVATION 3: [object Object]

OBSERVATION 2: [object Object]

OBSERVATION 3: [object Object]

What I believe is happening, is that the Angular components are loaded before any http call has returned, causing multiple requests at bootstrapping. What would be the correct and best way of mitigating this?

Upvotes: 2

Views: 684

Answers (2)

Arnaud H
Arnaud H

Reputation: 1011

Thanks to the hint from chrispy, I dove into Observables and it appears that they indeed are the preferred way of implementing async http calls. However, merely subscribing from within the components did not prevent multiple calls from the service to the API, I didn't get it to work until I found this answer. I'm not sure whether it is a best practise, but it works.

Upvotes: 0

chrispy
chrispy

Reputation: 3612

Try returning the request itself and performing the operation inside your component. Do you have to use promises? Angular prefers observables.

return this.http.get(this.apiUrl).map(res => res.json());

Then subscribe in each of your components.

Upvotes: 2

Related Questions