简体   繁体   English

RxJS可观察到:重复使用count然后使用notifier

[英]RxJS Observable: repeat using count and then using notifier

I have an Observable that emits Either = Success | Failure 我有一个Observable发出Either = Success | Failure Either = Success | Failure : Either = Success | Failure

import { Observable } from 'rxjs';

type Success = { type: 'success' };
type Failure = { type: 'failure' };

type Either = Success | Failure;

const either$ = new Observable<Either>(observer => {
    console.log('subscribe');
    observer.next({ type: 'failure' });
    observer.complete();
    return () => {
        console.log('unsubscribe');
    };
});

I want to allow the user to "retry" the observable when the Observable completes and the last value was Failure . 我想允许用户在Observable完成并且最后一个值为Failure时“重试” observable。

(The retry{,When} operators do not help here because they work with errors on the error channel. For this reason, I believe we should think in terms of repeat instead.) retry{,When}运算符在这里无济于事,因为它们在error通道上处理error 。因此,我相信我们应该考虑repeat

I want to: 我想要:

  • Repeat the Observable n times until the last value is not Failure . 重复Observable n次,直到最后一个值不是Failure
  • Then, allow the user to repeat manually. 然后,允许用户手动重复。 When a repeat notifier observable ( repeat$ ) emits, repeat the observable again. 当发出一个重复通知者observable( repeat$ )时,请再次重复该observable。

For example: 例如:

// subscribe
// next { type: 'failure' }
// unsubscribe

// retry 2 times:

// subscribe
// next { type: 'failure' }
// unsubscribe

// subscribe
// next { type: 'failure' }
// unsubscribe

// now, wait for repeat notifications…
// on retry notification:

// subscribe
// next { type: 'failure' }
// unsubscribe

I couldn't come up with something simpler, but the code does what you want. 我无法提出更简单的方法,但是代码可以满足您的要求。

See https://stackblitz.com/edit/typescript-yqcejk 参见https://stackblitz.com/edit/typescript-yqcejk

defer(() => {
   let retries = 0;

   const source = new BehaviorSubject(null);

   return merge(source, repeat$.pipe(filter(() => retries <= MAX_RETRIES)))
       .pipe(
           concatMapTo(either$),
           tap(value => {
               const action = value as Either;
               if (action.type === 'failure') {
                   if (retries < MAX_RETRIES) {
                       retries += 1;
                       source.next(null);
                   }
               } else {
                   retries = 0;
               }
           })
       )
}).subscribe(console.log);

I had to manually count retries. 我不得不手动计算重试次数。

The code has two sources of events source for automatic retries and repeat$ for user retries. 该代码有两个事件source ,它们分别是自动重试的事件sourcerepeat$的用户重试源。 All events are mapped to either$ using concatMapTo . 所有的事件映射到either$使用concatMapTo As a side-effect we either next() to retry or do nothing waiting for user to retry. 作为副作用,我们要么next()重试,要么不做任何等待用户重试的操作。

User retries are suppressed using filter(() => retries >= MAX_RETRIES) until MAX_RETRIES count is reached. 使用filter(() => retries >= MAX_RETRIES)抑制用户重试,直到达到MAX_RETRIES计数。

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

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