每次重试之前和之后发射

时间:2019-09-01 01:04:31

标签: rxjs ngrx

  1. 我有一部史诗,可以听某些动作。
  2. 一旦采取行动,就应该执行ajax.post
  3. 分行
    • 如果状态码正确,则发出YES
    • 如果状态不好,则发出pre,等待1秒,发出post

我为最后一颗子弹而苦苦挣扎,这是我在操场上的代码-https://rxviz.com/v/WJxGMl4O

这是我的管道部分:

action$.pipe(
    flatMap(action =>
        defer(() => ajax.post('foo foo foo')).pipe(
            tap(res => console.log('succeeded:', res)),
            mapTo('YES'),
            retryWhen(error$ =>
                error$.pipe(
                    tap(error => console.log('got error:', error)),
                    merge(of('pre')), // this isnt emiting
                    delay(1000),
                    merge(of('post')) // this isnt emitting
                )
            )
        )
    )
)

2 个答案:

答案 0 :(得分:2)

我认为您可以使用catchError而不是retryWhen来实现所需的目标,因为retryWhen仅对next通知做出反应,而不会进一步传播它们。使用catchError,您还可以获得源Observable,可以将其返回并重新订阅。 concat仅在前一个消息完成后才一个个地订阅所有源,因此它将先发送两条消息prepost,然后重试。

action$.pipe(
    filter(action => action === 'hi'),
    mergeMap(action =>
        defer(() => resolveAfter(3)).pipe(
            tap(res => console.log('succeeded:', res)),
            mapTo('YES'),
            catchError((error, source$) => {
                console.log('retrying, got error:', error);
                return staticConcat(
                    of('pre'),
                    of('post').pipe(delay(1000)),
                    source$,
                );
           }),
        )
    ),
    //take(4)
)

您的更新演示:https://rxviz.com/v/A8D7BzyJ

答案 1 :(得分:1)

这是我的方法:

首先,我创建了2个自定义运算符,一个将处理'pre'和'post'(skipValidation),另一个将处理逻辑(useValidation)。

const skipValidation = src => of(src).pipe(
  concatMap(
    v => of('post').pipe(
     startWith('pre'),
     delay(1000),
    ),
  ),
);

下面的代码段中值得注意的是action$.next({ skip: true })。这样,我们将发出将通过 iif运算符的新值,以便我们可以发出'pre'和'post';

const useValidation = src => of(src).pipe(
 filter(action => action === 'hi'),
    mergeMap(action =>
        defer(() => resolveAfter(3)).pipe(
            tap(res => console.log('succeeded:', res)),
            mapTo('YES'),
            delay(1000),
            retryWhen(error$ =>
                error$.pipe(
                        tap(error => { console.log('retrying, got error:', error); action$.next({ skip: true })}),
                        delay(1000),
                )
            )
        )
      )
);
action$.pipe(
    tap(v => console.log('v', v)), // Every emitted value will go through the `iif ` operator
    mergeMap(v => iif(() => typeof v === 'object' && v.skip, skipValidation(v), useValidation(v))),
)

Here is your updated demo