Запрос Http, сделанный несколько раз в службе Angular2

Я создал службу, которая делает простой запрос GET:

private accountObservable = null;

constructor(private _http: Http) {
}

getAccount () {
    // If we have account cached, use it instead
    if (this.accountObservable === null) {
        this.accountObservable = this._http.get('http://localhost/api/account')
            .map(res => <Account> res.json().data)
            .catch(this.handleError);
    }

    return this.accountObservable;
}

Я добавил эту службу в мою функцию bootstrap, чтобы предоставить ее по всему миру (я надеюсь предоставить один и тот же экземпляр всем компонентам):

provide(AccountService, { useClass: AccountService })

Проблема заключается в том, что когда я вызываю эту услугу в разных компонентах, каждый раз выполняется запрос GET. Поэтому, если я добавлю его к 3 компонентам, будут выполнены 3 запроса GET, хотя я проверю, существует ли уже наблюдаемое.

ngOnInit() {
  this._accountService.getAccount().subscribe(
    account => this.account = account,
    error =>  this.errorMessage = <any>error
  );
}

Как я могу предотвратить создание запроса GET несколько раз?

Ответ 1

Используйте Observable.share():

if (this.accountObservable === null) {
    this.accountObservable = this._http.get('./data/data.json')
      .share()
      .map(res => res.json())
      .catch(this.handleError);
}

Plunker

В Plunker, AppComponent и Component2 оба дважды звонят getAccount().subscribe().

С помощью share() на вкладке "Инструменты разработчика" Chrome Developer показан один HTTP-запрос для data.json. В share() закомментировано 4 запроса.

Ответ 2

Существует два типа наблюдаемых.

Холодный наблюдаемый: каждый абонент получает все события (начиная с самого начала)

Горячие наблюдаемые: каждый абонент получает события, которые выходят после подписки.

Холодные Observables являются стандартными. Это то, что вызов WS вызывает много раз.

Чтобы сделать Observable Hot, вы должны использовать следующую цепочку операторов Rx:

.publish().refCount()

В вашем случае:

getAccount () {

    let accountObservable = this._http.get('http://localhost/api/account')
            .map(res => <Account> res.json().data)
            .catch(this.handleError);

    return accountObservable.publish().refCount();
}

Ответ 3

В моем случае это было из-за того, что форма поста и кнопка-клик были настроены на одного слушателя.