RxJS和angular2

时间:2016-07-14 16:17:58

标签: asynchronous typescript angular undefined rxjs

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

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];
    }
}

问题是在调用properties时尚未加载getProperty。 如何让getProperty等待订阅填充数组? 我宁愿不返回对组件的订阅。



编辑:
我尝试了paulpdaniels回答并与pluck合作。但是我很快陷入困境。 所以基本上我有这个PropertyService返回HOST。 我有一个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
   }
}

如何实现这一目标?

2 个答案:

答案 0 :(得分:1)

简短的回答是,你不能,至少在没有为你的服务引入某种程度的异步性的情况下。

简单的事实是没有办法强制阻止行为并等待Observable完成,你应该返回一个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

弗兰克赫伯特曾写过(释义)&#34;流必须流动!&#34;。如果您需要使用嵌套的Observables运算符(例如flatMap),则可以将这些运算符展平为单个流,您可以继续链接。

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()); 
   }
}

答案 1 :(得分:0)

您可以做的是在observable本身返回properties,然后在目标服务中从该属性可观察开始,然后.flatMap http请求。这意味着引入更多的异步性,正如其他答案中提到的那样。 Othr解决方案是通过检索canActivate路由器防护中的属性,在app / component真正开始执行之前解析属性。在这种情况下,您可以确定当组件调用依赖于同步可用属性的其他服务的方法时,属性已经解析。