【问题标题】:RxJS and angular2RxJS 和 angular2
【发布时间】:2016-11-17 16:06:57
【问题描述】:

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

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

如何实现这一点?

【问题讨论】:

    标签: asynchronous typescript angular undefined rxjs


    【解决方案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

    正如弗兰克·赫伯特 (Frank Herbert) 曾经写道(释义)“溪流必须流动!”。如果您需要使用嵌套的 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()); 
       }
    }
    

    【讨论】:

    • 问题是我嵌套了可观察对象,因为我需要可观察对象的响应来生成新的可观察对象
    • 你只需要继续扩展 Observable,Observables 的好处是它们本质上是无限可扩展的。我会更新一个例子。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2017-05-04
      • 2017-09-04
      • 1970-01-01
      • 2016-10-29
      • 2016-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多