【问题标题】:Angular listen on subscription start of rxjs observable?Angular 监听 rxjs observable 的订阅开始?
【发布时间】:2021-11-15 07:13:44
【问题描述】:

有没有办法检测管道内可观察的 rxjs 订阅的开始?

我想在订阅 http observable(在响应完成后销毁)时触发加载指示器。

或者我是否必须为此操作创建一个可观察的包装器?

【问题讨论】:

标签: angular typescript rxjs


【解决方案1】:

这取决于您使用的 RxJS 版本。使用 RxJS defer():

defer(() => {
  loadingFlag = true;
  return this.http.doyourrequest().pipe(
    finalize(() => loadingFlag = false),
  );
});

由于 RxJS >= 7.3,您可以为 tap() 使用新的事件处理程序:

this.http.doyourrequest().pipe(
  tap({
    subscribe: () => loadingFlag = true,
    finalize: () => loadingFlag = false,
  }),
);

【讨论】:

    【解决方案2】:

    由于每次订阅 http observable 都会导致新的 http 调用,因此在管道外设置此类标志是安全的,至少我是这样做的。

    getSomeData(){
      loadingFlag=true;
      return this.http.doyourrequest().pipe(finalize(()=>loadingFlag=false));
    }
    

    如果你真的想通过子计数(由于 http obs 的最终化,每次请求后总是下降到 0)检查 refCount() 和 share() 内部计算订阅者的操作符的实现

    编辑:

    您可以使用 dummy observable 作为入口点来封装标志的设置,例如

    getSomeData(){
      return of(null).pipe(
          tap(()=>loadingFlag=true),
          switchMapTo(this.http.doyourrequest()),
          finalize(()=>loadingFlag=false)
      )
    }
    

    【讨论】:

    • 感谢您的回复。我已经像你一样实现了它,但是由于 httpobservable 上的引用,当我为它定义一个变量(让 obs$ = getSomeData())时,我面临着标志没有设置的问题。
    • 您可以使用 dummy observable 作为入口点来克服这个问题,并将映射到 observable 到 http - 在过程中设置标志。我已经添加了那个例子
    【解决方案3】:

    不要在流中设置一些指示符作为副作用,而是尝试创建一个返回请求状态的可观察对象。

    readonly makeRequestSubject = new Subject<RequestParams>();
    readonly request$ = makeRequestSubject.pipe(
      switchMap(params => this.doRequest(params).pipe(
        map(result => ({ params, result,  state: 'complete' })),
        catchError(error => ({ error, params, state: 'error' }))
        startWith({ params, state: 'loading' })
      ),
      startWith({ state: 'notstarted' }),
      shareReplay(1)
    );
    readonly isLoading$ = this.request.pipe(map(x => x === 'loading'), distinctUntilChanged());
    readonly results$ = this.request.pipe(map(x => x === 'complete' ? x.results : []));
    
    1. 可以从方法中返回一个可观察对象并像超重承诺一样使用它,或者您可以拥有一个包含流的字段,并且所有依赖项都可以在他们订阅和取消订阅它时想。 ma​​keRequestSubject 上的 next() 会在您每次需要发出新请求时被调用。
    2. 外部 startWith 应该首先发射。这是可选的,但在某些 ui 场景中可能很有用,例如在未发出请求时显示带有说明的消息。
    3. 请求是在 switchMap 中发起的,因此如果之前的调用尚未完成,成功的调用将中断它们。
    4. 内部的 startWith 运算符将首先发出,除非请求是即时的。
    5. catchError 说明了设置加载指示器之外的另一个典型用例。
    6. 您可以直接订阅 request$,也可以使用 isLoading$ 和 results$**。我通常会尽量避免创建额外的 observable,只是确保我的组件在主流中的模型与我的 ui 绑定匹配。
    7. 仅包含参数是因为它们可能在 ui 中有用。

    【讨论】:

      猜你喜欢
      • 2018-01-17
      • 1970-01-01
      • 1970-01-01
      • 2016-07-07
      • 2017-10-10
      • 1970-01-01
      • 2017-01-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多