当一个对象依赖于另一个对象的数据时处理可观察对象
handling observables when one is dependent on data from another
当一个 observable 运行时,它依赖于来自另一个 obseravble 的数据,我不知道如何正确处理这种依赖性。
一个 observable 从 Firebase 获取数据并通过订阅它创建一个简单的数字数组,称为 novelsRead: Array
另一个 observable 从 api 获得响应,通过订阅它意味着过滤掉 novelsRead[] 中存在 ID 的所有记录。
问题是,当响应来自 api 时,novelsRead[] 仍然是空的,因为 Firebase 尚未响应,所以不会从 api 响应中过滤任何内容。
代码如下:
导出class主页{
currentnovels: any;
novels: any;
unreadnovels: any;
nextnovels: any;
novel: any;
resultsPageNumber: number = 1;
novelFullPosterPath: any;
novelsread: Array<number> = [];
private basePosterUrlMedium = 'http://image.novels.org/t/p/w500';
private basePosterUrlSmall = 'http://image.novels.org/t/p/w185';
constructor(private http: Http,
private novelsApi: NovelsApiService,
private dataService: DataService,
) {
//this takes data from Firebase and pushes it to simple array of ids (numbers)
this.dataService.list('novels-read')
.subscribe(data => {
data.map(results => {
this.novelsread.push(results.novelsId);
})
})
}
ngAfterViewInit() {
this.novelsApi.getnovelsByPage(this.resultsPageNumber)
.subscribe(data => {
this.novels = data.results;
this.novels.map(data => {
data.full_poster_path = this.basePosterUrlMedium + data.poster_path;
return data;
})
.filter(data => {
let found = this.novelsread.indexOf(data.id);
//It seems when the api responds, this.novelsRead is still empty [] because Firebase has not responded yet
console.log("this novelsread[0] is ", this.novelsread[0]);
console.log("data.id found is ", found);
return data;
})
})
}
我正在寻找最简洁的解决方案,无论是使用事件、可观察链还是任何其他建议,例如将函数从构造函数移动到 ngAfterViewInit,反之亦然。
我确实查看了使用 combineLatest 组合可观察对象的代码示例,但发现语法非常复杂,想知道是否有更简洁的方法来实现我需要的东西,即使这涉及等待事件。
使用 forkJoin
应该对您有所帮助。
它只允许在两个请求都完成时处理结果:
https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/forkjoin.md
或者如果您的第二个请求取决于第一个响应 - 使用 switchMap
const request1$ = Rx.Observable.of('response1').delay(2000);
const request2$ = Rx.Observable.of('response2').delay(100);
Rx.Observable.forkJoin(request1$, request2$)
.subscribe(res => console.log(`forkJoin: ${res}`));
request1$.switchMap(res1 => {
console.log(`switchMap: ${res1}`);
return request2$;
}).subscribe(res2 => console.log(`switchMap: ${res2}`));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.3.0/Rx.min.js"></script>
当一个 observable 运行时,它依赖于来自另一个 obseravble 的数据,我不知道如何正确处理这种依赖性。
一个 observable 从 Firebase 获取数据并通过订阅它创建一个简单的数字数组,称为 novelsRead: Array
另一个 observable 从 api 获得响应,通过订阅它意味着过滤掉 novelsRead[] 中存在 ID 的所有记录。
问题是,当响应来自 api 时,novelsRead[] 仍然是空的,因为 Firebase 尚未响应,所以不会从 api 响应中过滤任何内容。
代码如下:
导出class主页{
currentnovels: any;
novels: any;
unreadnovels: any;
nextnovels: any;
novel: any;
resultsPageNumber: number = 1;
novelFullPosterPath: any;
novelsread: Array<number> = [];
private basePosterUrlMedium = 'http://image.novels.org/t/p/w500';
private basePosterUrlSmall = 'http://image.novels.org/t/p/w185';
constructor(private http: Http,
private novelsApi: NovelsApiService,
private dataService: DataService,
) {
//this takes data from Firebase and pushes it to simple array of ids (numbers)
this.dataService.list('novels-read')
.subscribe(data => {
data.map(results => {
this.novelsread.push(results.novelsId);
})
})
}
ngAfterViewInit() {
this.novelsApi.getnovelsByPage(this.resultsPageNumber)
.subscribe(data => {
this.novels = data.results;
this.novels.map(data => {
data.full_poster_path = this.basePosterUrlMedium + data.poster_path;
return data;
})
.filter(data => {
let found = this.novelsread.indexOf(data.id);
//It seems when the api responds, this.novelsRead is still empty [] because Firebase has not responded yet
console.log("this novelsread[0] is ", this.novelsread[0]);
console.log("data.id found is ", found);
return data;
})
})
}
我正在寻找最简洁的解决方案,无论是使用事件、可观察链还是任何其他建议,例如将函数从构造函数移动到 ngAfterViewInit,反之亦然。
我确实查看了使用 combineLatest 组合可观察对象的代码示例,但发现语法非常复杂,想知道是否有更简洁的方法来实现我需要的东西,即使这涉及等待事件。
使用 forkJoin
应该对您有所帮助。
它只允许在两个请求都完成时处理结果:
https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/forkjoin.md
或者如果您的第二个请求取决于第一个响应 - 使用 switchMap
const request1$ = Rx.Observable.of('response1').delay(2000);
const request2$ = Rx.Observable.of('response2').delay(100);
Rx.Observable.forkJoin(request1$, request2$)
.subscribe(res => console.log(`forkJoin: ${res}`));
request1$.switchMap(res1 => {
console.log(`switchMap: ${res1}`);
return request2$;
}).subscribe(res2 => console.log(`switchMap: ${res2}`));
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.3.0/Rx.min.js"></script>