我有一个角度应用程序,它使用一个服务来填充一个数组以在表中使用,但结果需要第二次转换才能准备好呈现。我正在调用另一个服务,但是在我提醒用户界面完成之前我怎么知道我完全完成所有转换?我试过这个(天真的方法),但它有一个缺陷:
this.dataService.getData().subscribe(result => {
result['entries'].forEach(entry => {
let fieldToTransform = entry['fieldToTransform'];
this.transformService.transform(fieldToTransform).subscribe(transformedField => {
entry['fieldToTransform'] = transformedField;
});// hmm, can't alert UI here
});// not here either
});
但很明显,循环的每次迭代都会调用服务并在不同时间完成。我怎么知道它们何时完成?
答案 0 :(得分:1)
如果可以提供帮助,请避免多次订阅。在这种情况下,我认为你可以。
我希望这个例子有意义。有许多方法/操作员可以实现您需要的变化。我在下面的示例中使用了concatMap()
,toArray()
,map()
。此示例假定您的第二个异步服务调用始终返回1个值。
// simulates first async service call
const sourceOne = Rx.Observable.of(1,2,3);
// simulates second async service call
const sourceTwo = Rx.Observable.of('something-from-two');
// for each value from source one, process it after getting a value from source two
const example = sourceOne.concatMap(sourceOneValue => {
return sourceTwo.map(sourceTwoValue => '---' + sourceOneValue + ':' + sourceTwoValue + '---')
})
// as separate values
example.subscribe(val => console.log(val));
// as a single array
// example.toArray().subscribe(val => console.log(val));
请参阅此runnable example并进行调整以满足您的需求。
这实际上是关于RxJS的问题,如果示例不充分,我建议进一步阅读该主题以满足您的特定用例。
答案 1 :(得分:0)
在您的第二个嵌套Observable
订阅中,您可以获得两次通话的结果。
this.dataService.getData().subscribe(result => {
result['entries'].forEach(entry => {
let fieldToTransform = entry['fieldToTransform'];
this.transformService.transform(fieldToTransform).subscribe(transformedField => {
entry['fieldToTransform'] = transformedField;
// <<< --- maybe here? you have results from both of your service methods
});// hmm, can't alert UI here
});// not here either
});
编辑:
那么你应该使用某种合并的Observable运算符。
http://reactivex.io/documentation/operators.html @ Combining Observables
这是一个例子(我现在无法验证它,但也许它可以帮助你一个想法):
this.dataService.getData().subscribe(result => {
let transformSubscriptions = [];
result['entries'].forEach(entry => {
let fieldToTransform = entry['fieldToTransform'];
const sub = this.transformService.transform(fieldToTransform)
.do(transformedField => {
entry['fieldToTransform'] = transformedField;
})
transformSubscriptions.push(sub);
});
Observable.combineLatest(transformSubscriptions)
.subscribe(results => window.alert('All transfers happened (at least once)'));
});