#angular #rxjs #rxjs5 #angular2-observables
#angular #rxjs #rxjs5 #angular2-наблюдаемые
Вопрос:
Вот мой код:
this._http.post(this._url_get extension, '', { headers: headers })
.map(res => res['_body'])
.retryWhen(errors => {return responseErrorProcess(errors)})
теперь мне нужно перехватывать исключения и передавать их в my, responseErrorProcess()
который возвращает true
, если требуется повторить попытку
Я не мог понять, как извлекать исключения из errors
, вот как это выглядит:
Subject_isScalar: falseclosed: falsehasError: falseisStopped: falseobservers: Array[0]thrownError: null__proto__: Observable`
Похоже, что она не содержит ошибок о возникающих исключениях, плюс я не мог понять, что я должен вернуть, чтобы на самом деле повторить попытку или нет.
Ответ №1:
retryWhen
должно возвращать наблюдаемое. Повторная попытка происходит, как только наблюдаемый выдает:
.retryWhen(errors =>
//switchMap to retrieve the source error
errors.switchMap(sourceErr =>
//send source to processor
responseErrorsProcess(sourceErr) ?
//if result is TRUE, emit (will cause retry). Else, pass on the error
Observable.of(true): Observable.throw(sourceErr)
)
)
Если вы хотите завершить вместо ошибки при возврате вашего процессора false
, замените Observable.throw()
на Observable.empty()
Ответ №2:
Вызываемое в retryWhen()
должно возвращать наблюдаемое, которое выдает complete
или error
для завершения потока или выдает значение для повторной подписки.
Например, этот код завершается без выдачи ошибки из-за Observable.empty()
:
Observable.create(obs => {
obs.next(1);
obs.next(2);
obs.error('error from source');
})
.retryWhen((errors) => {
errors.subscribe(sourceError => console.log(sourceError));
return Observable.create(obs => obs.error('inner error'));
})
.subscribe(
val => console.log(val),
err => console.log('error', err),
_ => console.log('complete')
);
Ошибка из наблюдаемого источника передается в errors
как next
. Смотрите исходный код:https://github.com/ReactiveX/rxjs/blob/master/src/operator/retryWhen.ts#L86
Это выводится на консоль:
1
2
error inner error
error from source
Смотрите живую демонстрацию:http://plnkr.co/edit/Fajsb54WJwB8J8hkUC6j?p=preview
Редактировать на основе комментариев ниже:
Посмотрите документацию для retryWhen()
:
Ошибка вызовет выдачу Throwable, которая вызывает ошибку для Observable, возвращаемого из notificationHandler. Если это наблюдаемое вызывает onComplete или error, то повторная попытка вызовет complete или error для дочерней подписки. В противном случае это наблюдаемое значение будет повторно подписано на исходное наблюдаемое значение в конкретном планировщике.
Таким образом, наблюдаемая величина, возвращаемая при обратном вызове, отвечает за принятие решения о повторной подписке. Если он выдает next()
, то повторите подписку. Если оно выдает error()
или complete()
передает их дочернему наблюдателю.
Например, вы могли бы сделать (я не тестировал этот код):
return response.retryWhen((errors) => {
var retrySource = new Subject();
errors.subscribe(error => {
if (this.responseErrorProcess(error)) retrySource.next();
else retrySource.complete();
});
return retrySource;
});
В соответствии с вашей внутренней логикой вы запускаете правильное сообщение на retrySource
.
Комментарии:
1. Спасибо! но как получить ошибки? вы видите, ошибка, которую мы получаем подобным образом, является наблюдаемой и на самом деле не содержит исключения, не та ошибка, которую я бы получил с помощью .catch(), которая на самом деле содержит http-ответ (извините за мой слабый способ объяснения)
2. @MotassemMK Смотрите мой обновленный ответ. Это работает точно так, как это задокументировано в reactivex.io/rxjs/class/es6 /… . Тем не менее, я согласен, что описание очень часто бывает очень запутанным.
3. что ж, отлично, я получил ошибки! но (и, извините, это второй последующий вопрос) как я могу вернуть значение retryWhen изнутри flatMap как его асинхронное? это то, что я пробовал:
4. @MotassemMK Я обновил свой ответ, посмотрите внизу.
5. @MotassemMK Ты прав, используй
subscribe()
вместоflatMap