简体   繁体   English

在 rxjs observable 订阅开始时进行 Angular 侦听?

[英]Angular listen on subscription start of rxjs observable?

Is there a way to detect the start of the subcription of a rxjs observable within the pipe?有没有办法检测管道内可观察的 rxjs 的订阅开始?

I want to trigger a loading indicator when a http observable (destroyed when respone has been finalized) get subscribed.我想在订阅 http observable(在响应完成时销毁)时触发加载指示器。

Or do I have to create a wrapper observable for this action?或者我是否必须为此操作创建一个可观察的包装器?

It depends on what RxJS version you're using.这取决于您使用的 RxJS 版本。 With RxJS < 7.3 you can use defer() :使用 RxJS < 7.3 你可以使用defer()

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

Since RxJS >= 7.3 you can use new event handlers for tap() :由于 RxJS >= 7.3 你可以为tap()使用新的事件处理程序:

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

since every subscription to http observable causes new http call it is safe to set such flag outside of the pipe, at least it is how I do it.由于对 http observable 的每个订阅都会导致新的 http 调用,因此在管道外设置此类标志是安全的,至少我是这样做的。

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

if you really want to go trough sub count(which is always down to 0 after every request due to finalizztion of http obs) check the implementation of refCount() and share() operators which internally counts the subscribers如果你真的想通过子计数(由于 http obs 的 finalizztion,每次请求后总是下降到 0)检查 refCount() 和 share() 运算符的实现,它们在内部对订阅者进行计数

Instead of setting some indicator as a side effect in your stream, try creating an observable that returns the state of your request.不要在您的流中设置一些指标作为副作用,而是尝试创建一个返回请求状态的 observable。

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. You could return an observable from a method and use it like an overweight promise, or you could have a single field that contains the stream, and all dependents could just subscribe and unsubscribe to it when they want.可以从一个方法返回一个 observable 并像一个超重的承诺一样使用它,或者你可以有一个包含流的字段,所有依赖者都可以在他们想要的时候订阅和取消订阅它。 next() on makeRequestSubject gets called every time you need to make a new request.每次您需要发出新请求时,都会调用makeRequestSubject上的next()
  2. The outer startWith should emit first.外部startWith应该首先发射。 This is optional, but might be useful in some ui scenarios, such as showing a message with instructions if no requests have been made.这是可选的,但在某些 ui 场景中可能很有用,例如如果没有发出请求,则显示带有说明的消息。
  3. The request is initiated in a switchMap so succcessive calls will interrupt the prior ones if they're not already complete.该请求是在switchMap 中发起的,因此如果先前的调用尚未完成,则连续调用将中断它们。
  4. The inner startWith operator will emit first unless the request is instantaneous.除非请求是即时的,否则内部startWith运算符将首先发出。
  5. catchError illustrates another typical use case beyond settings a loading indicator. catchError说明了除了设置加载指示器之外的另一个典型用例。
  6. You could subscribe to request$ directly, or use isLoading$ and results$**.您可以直接订阅request$ ,也可以使用isLoading$和 results$**。 I typically try to avoid creating extra observables, and just make sure the model on my component in a master stream matches up with my ui bindings.我通常会尽量避免创建额外的 observable,只需确保主流中组件上的模型与我的 ui 绑定匹配。
  7. Params were just included because they might be useful in the ui.参数只是被包含在内,因为它们可能在 ui 中有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM