Angular2: возврат геттера после завершения конструктора в службе (http get)

Для моего приложения мне нужно использовать List.json для создания списка (ядро моего приложения). Чтобы разделить этот список между всеми моими компонентами, я решил создать сервис.

В этом сервисе я вызываю свой файл json в конструкторе и использую геттер, чтобы получить этот список в других компонентах. Но когда я вызываю геттер, конструктор не закончился (http get немного медленный) и ничего не возвращает.. (с небольшим тайм-аутом все работает нормально, но это грязно)

Можно ли вызвать геттер после завершения конструктора?

Заранее спасибо !

Мой сервис:

import {Injectable} from "angular2/core";
import {Http, Response, HTTP_PROVIDERS} from 'angular2/http';

@Injectable()
export class listService {
    private list;


    constructor(http: Http) {
        http.get('app/List.json')
            .map(res => res.json())
            .subscribe(
              data => this.list = data 
            );
    }


    getValue(){
        return this.list;
    }
}

Мой компонент, который отображает список:

import {listService} from './listService';
import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES, Router} from 'angular2/router';
import 'rxjs/add/operator/map';

@Component({
  selector: 'list',
  template: `
    <h2>Formations </h2>
    <ul><li (click)='showItem(item)'  *ngFor="#item of list"><span >{{item.Method}}</span></li></ul>
`,
  directives: [ROUTER_DIRECTIVES]
})
export class List {
  public list: Object[];
  constructor(private listService:listService, private _router: Router) {
      this.list = this.listService.getValue();
  }
  showItem(item){
    this._router.navigate( ['Item', { id: item.id }] );
  }  
}

person Gen    schedule 31.03.2016    source источник
comment
Дубликат stackoverflow.com/questions/36083114/ ?   -  person Günter Zöchbauer    schedule 31.03.2016


Ответы (3)


Вы можете использовать наблюдаемую как результат вашего метода getValue. Таким образом, компоненты будут уведомлены со значением.

@Injectable()
export class listService {
  private list;
  private obs;

  constructor(http: Http) {
    this.obs = http.get('app/List.json')
        .map(res => res.json())
        .do(
          data => {
            this.list = data;
        ).share();
  }

  getValue() {
    if (this.list) {
      return Observable.of(this.list);
    } else {
      return this.obs;
    }
  }
}

Обновить

В вашем компоненте вам нужно зарегистрироваться в возвращаемом наблюдаемом объекте:

@Component({
})
export class SomeComponent {
  constructor(private service: listService) {
    this.service.getValue().subscribe(
      (list) => {
        // do something with the list
      });
  }
}
person Thierry Templier    schedule 31.03.2016
comment
Спасибо за этот пример! Но share() кажется неопределенной, и как мне использовать возврат getValue() в моем компоненте? Большое спасибо - person Gen; 01.04.2016
comment
Пожалуйста! По умолчанию все наблюдаемые операторы не включены. Вы можете попробовать импортировать следующее: import 'rxjs/Rx. Подробнее см. в этом вопросе: stackoverflow.com/questions/34515173/ - person Thierry Templier; 01.04.2016
comment
Еще раз спасибо за этот быстрый ответ! Я думаю, что я делаю что-то не так, я импортирую import 'rxjs/Rx' и в моем индексе <script src="node_modules/rxjs/bundles/Rx.js"></script>, но у меня все еще есть ошибка undefined - person Gen; 01.04.2016
comment
Выглядит неплохо! О, в одном из моих фрагментов была опечатка. Оператор do должен использоваться в сервисе вместо подписки. Сейчас должно быть лучше. Извиняюсь! - person Thierry Templier; 01.04.2016

Используя подход из https://stackoverflow.com/a/36296015/217408

Он хранит наблюдаемую, возвращаемую getValue(). Наблюдаемое построено таким образом, что несколько подписчиков получают одно и то же значение.

Невозможно напрямую получить значение асинхронных вызовов, таких как http.get()

import {Injectable} from "angular2/core";
import {Http, Response, HTTP_PROVIDERS} from 'angular2/http';

@Injectable()
export class listService {
    private list;


    constructor(http: Http) {
        this.observable = this.http.get('app/List.json')
            .map(res => res.json()).publishLast().refCount();

    }


    getValue(){
        return this.observable;
    }
}
import {listService} from './listService';
import {Component} from 'angular2/core';
import {RouteConfig, ROUTER_DIRECTIVES, Router} from 'angular2/router';
import 'rxjs/add/operator/map';

@Component({
  selector: 'list',
  template: `
    <h2>Formations </h2>
    <ul><li (click)='showItem(item)'  *ngFor="#item of list"><span >{{item.Method}}</span></li></ul>
`,
  directives: [ROUTER_DIRECTIVES]
})
export class List {
  public list: Object[];
  constructor(private listService:listService, private _router: Router) {
      this.listService.getValue().subscribe(value => this.list = value);
  }
  showItem(item){
    this._router.navigate( ['Item', { id: item.id }] );
  }  
}
person Günter Zöchbauer    schedule 01.04.2016
comment
Спасибо за Ваш ответ ;) - person Gen; 01.04.2016

person    schedule
comment
Спасибо за ваш ответ, но с вашим кодом я буду использовать запрос каждый раз, когда я вызываю геттер. - person Gen; 31.03.2016