RxJS 管道函数忽略 observable

RxJS pipe function disregarding observable

我正在将应用程序从 Promises 升级到 RxJS,我不确定我是否在正确的轨道上。

案例: 给定一个 ModalComponant,它在发送 HTTP 请求时加载并在收到响应时销毁。 所以我的做法如下

public post(uri: string, body: object, showLoading: boolean = true, params: object = {}): Observable<any> {
if (showLoading) {
  this.toggleModal('open');
}

return this.http.post(
  this.createUrl(uri),
  body,
  this.createOptionsWrapper(params)
)
.pipe(
  this.toggleModal('close'),
  catchError(err => this.handleError(err))
);

}

toggleModal() 接受 1 个参数并基于它 open/close 模式。我了解 pipeable Operators 必须 return 一个 OperatorFunction 类型。对于上述情况,你认为最合适的 RxJS 运算符是什么,我不接触 Observable 本身,我只是想让它可管道化,以便它按给定的顺序运行?可能值得自己创建一个自定义的?当然,这里被 returned 的 Observable 将在注入服务的任何地方再次通过管道传输。

如果您不想修改响应结果,请使用 tap 运算符。

return this.http.post(
  this.createUrl(uri),
  body,
  this.createOptionsWrapper(params)
)
.pipe(
      tap( () => this.toggleModal('close') ),
      catchError(err => this.handleError(err))
);

IMO finalize 操作员最适合这里。它在源完成或出错时调用,并且不会修改可观察对象的发射。

public post(
  uri: string, 
  body: object, 
  showLoading: boolean = true,
  params: object = {}
): Observable<any> {
  if (showLoading) {
    this.toggleModal('open');
  }

  return this.http.post(
    this.createUrl(uri),
    body,
    this.createOptionsWrapper(params)
  ).pipe(
    finalize(() => {
      if (showLoading) {
        this.toggleModal('close');
      }
    }),
    catchError(err => this.handleError(err))
  );
}

@Michael D 是正确的 IMO,finalize 是正确的运算符,但我也相信你应该将其包装在 defer:

public post(uri: string, body: object, showLoading: boolean = true, params: object = {}): Observable<any> {
  return defer(() => {
    if (showLoading) {
      this.toggleModal('open');
    }

    return this.http.post(
      this.createUrl(uri),
      body,
      this.createOptionsWrapper(params)
    ).pipe(
      finalize(() => this.toggleModal('close')),
      catchError(err => this.handleError(err))
    );
  });
}

原因是 observables 期望它们不做任何事情,除非它们被订阅。所以如果你只是像这样构建一些条件:

let save$ = this.service.post(...)
if (id) {
   save$ = this.service.put(...)
}
save$.subscribe();

在您真正订阅之前,模式不会被切换。如果没有延迟,模态将在第 1 行切换。一般的观点是,如果没有 defer,您会创建模态可能会打开的情况,如果您从不订阅,则永远不会关闭。使用 defer 确保永远不会发生。