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];
}
}
问题是调用getProperty
时properties
还没有加载。
如何让 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 中检索属性来解析属性。在这种情况下,您可以确定当组件调用其他服务的方法时,这取决于同步可用的属性,这些属性已经被解析。
假设我有一个获取属性列表的服务:
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];
}
}
问题是调用getProperty
时properties
还没有加载。
如何让 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 中检索属性来解析属性。在这种情况下,您可以确定当组件调用其他服务的方法时,这取决于同步可用的属性,这些属性已经被解析。