Еще один интересный факт заключается в том, что при использовании той же самой логики повтора c для службы, используемой в эффекте, она работает просто отлично.
retry(n)
просто пройдет вместе с уведомлением об ошибке при достижении n
попыток. При попытках <<code>n он отписывается от источника, а затем повторно подписывается .
retryWhen(fn)
поддерживает внутреннюю подписку, которая является результатом наблюдаемой обеспечивается функцией fn
. Единственный аргумент fn
- это субъект ошибок , который будет принимать значения sh каждый раз, когда возникает ошибка.
Итак, если у вас есть
retryWhen(subjectErrors => subjectErrors.pipe(a(), b()))
по сути такой же, как:
const subjectErrors = new Subject();
subjectErrors.pipe(a(), b()).subscriber(innerSubscriber);
* * * * * * * * * * * * * * * * * * * * * * * innerSubscriber
* * * * * также используется в retryWhen
, и его основная роль заключается в том, чтобы сообщать, когда приходит значение (next notification
).
Когда это произойдет, источник будет переподписан . В этом случае источником является наблюдаемая, которая отправляет http-запрос, а при возникновении ошибки отправляет уведомление error
; если запрос выполнен успешно, он выдаст уведомление next
, а затем уведомление complete
.
take(5)
от retryWhen(errors => errors.pipe(delay(1000), take(5)))
означает, что при достижении 5 попыток innerSubscriber
(та, что сверху) выдаст уведомление complete
.
Тогда у вас будет last
с значением по умолчанию . Это означает, что когда он получает уведомление complete
, без получения каких-либо уведомлений next
ранее, он выдаст ошибку (поведение по умолчанию).
Тогда ошибка будет зафиксирована catchError()
в вашем действии. Так что это должно объяснить, почему этот подход работает.
Что странно, это то, что когда http-перехватчик использует оператор, а не повторяет попытку, когда он работает просто отлично.
Это то, что я не могу объяснить, потому что, используя информацию из предыдущего раздела, она должна работать нормально, созданные потоки должны быть идентичны.
Если у вас есть
load () {
return this.http.get(...);
}
и предполагая, что перехватчик - единственный, который вы используете, в
mergeMap(() =>
this.globalStatsService.load().pipe(
map(stats =>
globalStatsActions.loaded({
latestStats: stats
})
),
catchError(() => of(globalStatsActions.loadFailed())) // not being called using the http-interceptor
)
)
this.globalStatsService.load()
должен быть такой же, как
of(request).pipe(
concatMap(
req => new Observable(s => { /* making the request.. */ }).pipe(
retryWhen(errors => errors.pipe(delay(1000), take(5))),
last(),
)
)
)
, который должен быть таким же, как в случае с предыдущий раздел.
Так что, если я ничего не пропустил, нужно набрать catchError
.
Если нет, это может означать, что у вас есть какой-то другой catchError
или last
получил значение и поэтому не выдает ошибку.
В этом случае что-то регистрируется?
// here the NGRX failure action is not being triggered after five failing requests
return httpHandler.handle(nextRequest).pipe(
retryWhen(errors => errors.pipe(delay(1000), take(5))),
tap(console.log),
last()
);
Редактировать
Как видно из исходный код , наблюдаемый в котором запрос будет Я отправляю через своего подписчика событие, которое указывает, что запрос был отправлен.
Имея это в виду, вы можете использовать оператор filter
:
return httpHandler.handle(nextRequest).pipe(
filter(ev => ev.type !== 0),
retryWhen(errors => errors.pipe(delay(1000), take(5))),
last()
);