如果内部有forkconne,请避免嵌套订阅



这是我在角度中的代码

this.service.save(body).subscribe(
resp => {
this.dialog.confirmation({
message: 'save object successfully!'
})
.subscribe((ok) => {
if(ok) {
this.pro.status = resp.status;
this.loadingData(resp);
const s1 = this.service.getSummary(this.id);
const s2 = this.service.getCost(this.id);
forkJoin([s1, s2]).subscribe([r1, r2]) => {
this.view = r1;
this.list = r2;
}
}
});
}
);

所以有很多级别的订阅。它不仅丑陋,而且结果是错误的,我无法通过调试找到它。如何使用rxjs运算符重写它?

您可以使用RxJS运算符来简化它,如下所示:

// import { EMPTY, forkJoin } from 'rxjs';
// import { map, mergeMap } from 'rxjs/operators';
this.service
.save(body)
.pipe(
mergeMap((result) =>
// Merge the main observable with the dialog confirmation one..
// and map it to an object that contains the result from both observables.
this.dialog
.confirmation({ message: 'save object successfully!' })
.pipe(map((confirmed) => ({ result, confirmed })))
),
mergeMap(({ result, confirmed }) => {
if (confirmed) {
this.pro.status = result.status;
this.loadingData(result);
const s1 = this.service.getSummary(this.id);
const s2 = this.service.getCost(this.id);
return forkJoin([s1, s2]);
}
// Don't emit any value, if the dialog is not confirmed:
return EMPTY;
})
)
.subscribe(([r1, r2]) => {
this.view = r1;
this.list = r2;
});

注意:为了处理内存泄漏,强烈建议在您不再需要unsubscribe时,从可观察的角度使用它,这可以根据您的用例来实现,例如将subscribe函数结果分配给Subscription变量并在ngOnDestroy生命周期挂钩中调用unsubscribe,或者使用带有takeUntil运算符的Subject并在ngOnDestroy中调用next/complete函数。

以下是如何使用unsubscribe方法的示例:

// import { Subscription } from 'rxjs';
@Component({...})
export class AppComponent implements OnInit, OnDestroy {
subscription: Subscription 
ngOnInit(): void {
this.subscription = this.service.save(body)
// >>> pipe and other RxJS operators <<<
.subscribe(([r1, r2]) => {
this.view = r1;
this.list = r2;
});
}
ngOnDestroy() {
this.subscription.unsubscribe()
}
}

你可以在这里阅读更多信息:https://blog.bitsrc.io/6-ways-to-unsubscribe-from-observables-in-angular-ab912819a78f

这应该大致等效:

this.service.save(body).pipe(
mergeMap(resp => 
this.dialog.confirmation({
message: 'save object successfully!'
}).pipe(
// This filter acts like your `if(ok)` statement. There's no 
// else block, so if it's not okay, then nothing happens. The 
// view isn't updated etc.
filter(ok => !!ok),
mapTo(resp)
)
),
tap(resp => {
this.pro.status = resp.status;
// If the following line mutates service/global state,
// it probably won't work as expected
this.loadingData(resp); 
}),
mergeMap(_ => forkJoin([
this.service.getSummary(this.id),
this.service.getCost(this.id)
]))
).subscribe([view, list]) => {
this.view = view;
this.list = list;
});

最新更新