我有这个功能:
getData(): Observable<ServerResponse> {
const data = {} as ServerResponse;
data.client = this.getClientData().pipe(
map(response =>
response.map(x => {
return x.data.client;
}),
),
);
data.otherData = this.otherData().pipe(
map(response =>
response.map(x => {
return this.groupByTimePeriod(x.data.other, 'day', 'week');
}),
),
);
}
该函数需要返回data
,其中包含在函数内部分配给该属性的所有属性。你会怎么做?
如果我只返回了data
,那么它就不能工作,因为this.getClientData()
并且this.otherData()
尚未完成。
答案 0 :(得分:1)
好吧,您在这里有多个问题。我将从最简单的开始。您如何从函数/对象中获得可观察物?答案是通过可观察的of:
return of(data);
但是您遇到了一个更大的问题,那就是:如何将返回数据推迟到子可观察变量发出其值之前?您正在寻找forkJoin。通过文档:
forkJoin
将等待所有传递的Observable完成,然后它将发出一个数组,其中包含来自相应Observable的最后一个值。因此,如果将n
Observables传递给运算符,则结果数组将具有n
值,其中第一个值是第一个Observable发出的最后一个值,第二个值是第二个Observable发出的最后一个值,并且以此类推。这意味着forkJoin
不会发射超过一次,并且将在此之后完成。
您还有其他一些问题。例如,您永远不会订阅this.getClientData()
或this.otherData()
。观察变量是懒惰地执行的。可观察对象中的代码将在某些内容订阅后才能执行。来自the docs:
Observable.create(function subscribe(observer) {...})
中的代码表示“可观察的执行”,仅对每个订阅的观察者进行的惰性计算。
它似乎也好像您在使用pipe/map
来试图在data
对象上设置属性一样。但是您永远不会设置data.client
或data.other
,因此它们将始终为空。
综上所述,代码看起来像这样,模拟服务器延迟显示forkJoin
等待两个可观察对象的完成:
import { Injectable } from '@angular/core';
import { Observable, of, forkJoin } from 'rxjs';
import { delay } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class TestService {
getData(): Observable<ServerResponse> {
const allOperations = forkJoin(
this.getClientData(),
this.getOtherData()
);
const observable = Observable.create(function subscribe(observer) {
// Wait until all operations have completed
allOperations.subscribe(([clientData, otherData]) => {
const data = new ServerResponse;
// Update your ServerReponse with client and other data
data.otherdata = otherData.other;
data.client = clientData.client;
// Now that data is 100% populated, emit to anything subscribed to getData().
observer.next(data);
observer.complete();
});
});
// We return the observable, with the code above to be executed only once it is subscribed to
return observable;
}
getClientData() : Observable<any> {
return of({ client: 'Client 1' });
}
getOtherData(): Observable<any> {
// Fake server latency
return of({ other: 'Other data that takes a while to return from server...' })
.pipe(delay(2000));
}
}
export class ServerResponse {
client: string;
otherdata: string;
}
如果您致电getData()
并订阅了可观察对象,您将看到forkJoin
可以正常工作,我们必须等待2秒才能完成两个儿童可观察对象的完成工作,我们的可观察对象发出一个值:
this.testService.getData().subscribe(data => {
console.log(data);
});
似乎您可能不熟悉RxJS /异步编程。我建议您有机会时向RxJs阅读the excellent introduction。刚开始时可能会很棘手,但随着实践的发展,这将成为第二天性。