2つのObservableでforkJoin
を使用しようとしています。それらの1つはストリームとして開始します...直接サブスクライブすると応答が返されますが、forkJoin
は起動しません。何か案は?
private data$: Observable<any[]>;
private statuses$: Observable<any[]>;
private queryStream = new Subject<string>();
....
this.data$ = this.queryStream
.startWith('')
.flatMap(queryInput => {
this.query = queryInput
return this._companyService.getCompanies(this.queryRequired + ' ' + this.query, this.page, this.sort);
})
.share();
...
Observable.forkJoin(this.statuses$, this.companies$)
.subscribe(res => {
console.log('forkjoin');
this._countStatus(res[0], res[1]);
});
// This shows arrays in the console...
this.statuses$.subscribe(res => console.log(res));
this.companies$.subscribe(res => console.log(res));
// In the console
Array[9]
Array[6]
forkJoin
の非常に一般的な問題は、すべてのソースObservableが少なくとも1つのアイテムを発行する必要があり、それらすべてを完了する必要があることです。
言い換えれば、this.statuses$
またはthis.companies$
はアイテムを放出せず、両方が完了するまでforkJoin
は何も放出しません。
this.statuses$.subscribe(
res => console.log(res),
undefined,
() => console.log('completed'),
);
forkJoin
は、すべての内部オブザーバブルが完了したときにのみ発行されます。各ソースからの単一の放出をリッスンするだけのforkJoin
に相当するものが必要な場合は、combineLatest
+ take(1)
を使用します。
_combineLatest(
this.statuses$,
this.companies$,
)
.pipe(
take(1),
)
.subscribe(([statuses, companies]) => {
console.log('forkjoin');
this._countStatus(statuses, companies);
});
_
両方のソースが発行するとすぐに、combineLatest
が発行し、その直後にtake(1)
がサブスクライブを解除します。
forkJoin
が機能しなかったため、以下のコードを使用して問題を解決しました。 mergeMap
を使用すると、外部サブスクリプションの結果を内部サブスクリプションにマップして、必要に応じてサブスクライブできます。
this.statuses$.pipe(
mergeMap(source => this.companies$.pipe(
map(inner => [source , inner])
)
)
).subscribe(([e , r]) => {
console.log(e , r);
})
Observable.forkJoin([
_someService.getUsers(),
_someService.getCustomers(),
])
.subscribe((data: [Array<User>, Array<Customer>]) => {
let users: Array<User> = data[0];
let customer: Array<Customer> = data[1];
}, err => {
});
//someService
getUsers():Observable<User> {
let url = '/users';
return this._http.get(url, headers)
.map(res => res.json());
}
getCustomers():Observable<Customer> {
let url = '/customers';
return this._http.get(url, headers)
.map(res => res.json());
}