RxJS 和 angular2

RxJS and angular2

假设我有一个获取属性列表的服务:

export class PropertyService {
    private properties: any;

    constructor(@Inject(Http) http) {
        this.http.get('/properties.json')
        .map((res:Response) => res.json())
        .subscribe(
            data => this.properties = data
        );
    }

    getProperty(property: string) {
        this.properties[property];
    }
}

问题是调用getPropertyproperties还没有加载。 如何让 getProperty 等待订阅填充数组? 我不想 return 订阅这些组件。



编辑:
我尝试了 paulpdaniels 的回答并与 pluck 一起工作。但是我很快就卡住了。 所以基本上我有这个 return 是 HOST 的 PropertyService。 我有一个 ApiService,它使用该主机执行另一个 ajax 调用以获取数据。

export class PropertyService {
    private properties: any;

    constructor(@Inject(Http) http) {
        this.properties = http.get('/properties.json')
            .map((res:Response) => res.json()).cache(1);
    }

    getProperty(property: string) {
        this.properties.pluck(property);
    }
}


export class ApiService {
    private http: Http;
    private host: string;

    constructor(@Inject(Http) http, @Inject(PropertyService) propertyService) {
        this.http = http;
        this.host = propertyServiceService.getProperty("API.URL"); //Is a subscription
    }

   getData(): any {
       //Here I must subscribe to host, and once available, 
       //use host to do an ajax call that returns another Observable for the component
   }
}

如何实现?

简短的回答是你不能,至少不能在你的服务中引入某种程度的异步性。

简单的事实是没有办法强制阻塞行为并等待 Observable 完成,您应该 return 一个 Observable 然后您的组件也应该知道如何消费。

export class PropertyService {
  private properties: Observable<any>;

  constructor(@Inject(Http) http) {
    this.properties = this.http.get('/properties.json')
                             .map((res:Response) => res.json())
                             //This will hold onto a cached value of the result
                             //without re-executing
                             .cache(1);

  }

  getProperty(property: string) {
    this.properties.pluck(property);
  }
}

编辑 1

正如 Frank Herbert 曾经写过的(释义)"the stream must flow!"。如果您需要使用像 flatMap 这样的嵌套 Observables 运算符,您可以将它们扁平化为单个流,您可以继续将其链接起来。

export class ApiService {
    private http: Http;
    private host: Observable<string>;

    constructor(@Inject(Http) http, @Inject(PropertyService) propertyService) {
        this.http = http;
        this.host = propertyServiceService.getProperty("API.URL"); //Is an Observable
    }

   getData(): Observable<any> {
       return this.host.flatMap(url => this.http.get(url), (_, res) => res.json()); 
   }
}

你可以做的是 return properties 在 observable 本身,然后在目标服务中从那个 observable 属性开始,然后 .flatMap 一个 http 请求。这意味着像其他答案中提到的那样引入更多的异步性。其他解决方案是在应用程序/组件真正开始执行之前通过在 canActivate router guard 中检索属性来解析属性。在这种情况下,您可以确定当组件调用其他服务的方法时,这取决于同步可用的属性,这些属性已经被解析。