【发布时间】:2021-08-31 03:02:12
【问题描述】:
在工作中,我们经常使用以下模式来响应我们应用程序中的某些事件。
class FooService {
public doFoo(): void {/* HttpRequest that eventually causes onFoo to emit */}
public onFoo!: Observable<unknown>;
}
class BarService {
public doBar(arg: unknown): void {/* HttpRequest that eventually causes onBar to emit */}
public onBar!: Observable<unknown>;
}
@Component({
selector: 'foo, [foo]',
templateUrl: './foo.component.html',
styleUrls: ['./foo.component.scss'],
})
export class FooComponent implements OnDestroy {
private fooSubscription: Subscription;
private barSubscription: Subscription;
constructor(private fooService: FooService, private barService: BarService) {
this.fooSubscription = fooService.onFoo.subscribe(this.handleFoo.bind(this));
this.barSubscription = barService.onBar.subscribe(this.handleBar.bind(this));
this.fooService.doFoo();
}
public models: unknown;
public ngOnDestroy() {
this.fooSubscription.unsubscribe();
this.barSubscription.unsubscribe();
}
private handleFoo(result: unknown) {
/* Do some work with result, then trigger next request */
this.barService.doBar(result);
}
private handleBar(result: unknown) {
/* Do actual work with data */
this.models = result;
}
}
注意 1 这始终用作链,因此
handleBar永远不会被独立调用,事实上,由于某些名为doBar()的不相关组件可能会触发它是不希望的行为.
注意 2 我宁愿不碰服务,因为担心它会破坏整个应用程序。
这通常会导致大量订阅和大量样板代码。我想用 rxjs 可观察链替换它,并用 angulars 异步管道绑定数据。我想出了以下代码:
constructor(private fooService: FooService, private barService: BarService) {
this.modelObservable = this.fooService.onFoo.pipe(
tap((result) => this.handleFoo(result)),
concatMap(() => this.barService.onBar),
tap((result) => this.handleBar(result))
);
this.fooService.doFoo();
}
private handleFoo(result: unknown) {
/* bit of validation on result */
this.barService.doBar();
}
private handleBar(result: unknown):unknown {/* Do actual work with data and return modified data*/}
所以modelObservable 最终会发出handleBar 返回的值,而异步管道会负责订阅和取消订阅,所以我不必这样做。
但是,我怀疑这是否可行,因为可观察链将调用handleFoo,它会调用doBar() 在实际上在concatMap 中订阅onBar。我不喜欢在这里依赖时间或概率。尽管如此,这个解决方案能否奏效?或者是否有可能“错过”来自onBar 的发射?有没有更好的解决方案来获得一个相同的可观察对象?也许另一个 rxjs 运算符(还没有使用那么多)?或者根本不可能将这个过程组合成一个单独的 observable?
【问题讨论】:
-
你也可以把这个
this.barService.doBar();放在pipe()链里面,而不是放在handleFoo()里面 -
@GaurangDhorda 那会改变什么?我真的不知道应该把它放在哪里,请随时在答案中解释:)