Как я могу узнать, завершился ли Observable с ошибкой или без ошибки?

Мне нужно выполнить некоторый код, когда Observable будет завершен, в зависимости от того, был ли он завершен с ошибкой или без. У меня есть этот код:

const obs = getMyObservable().pipe(finalize(() => {
    //here
}));

Как видите, я использую оператор finalize, но я не могу знать, был ли он завершен с ошибкой или без нее. Есть ли какие-то операторы doOnComplete или doOnError в rxjs?


person Héctor    schedule 18.05.2018    source источник


Ответы (3)


Согласно https://www.learnrxjs.io/

С последним RXJS вы можете использовать эти 3 оператора

const obs = getMyObservable().pipe(                                       // Let's assume 'obs' returns an array
    tap(() => console.log('Action performed before any other')),
    catchError(() => { console.error('Error emitted'); return of([]); }), // We return [] instead
    finalize(() => console.log('Action to be executed always'))           // Either Error or Success
);
obs.subscribe(data => console.log(data));  // After everything, we log the output.

Надеюсь, поможет

ИЗМЕНИТЬ на основе комментария JoniJnm

Чтобы быть более конкретным, есть 3 основных канала:

  1. Пайпы, которые изменяют результат перед подпиской.
  2. Пайпы, которые не меняют результат до подписки.
  3. Специальные трубы.

Например, Tap относится ко второму типу, он может принимать входные данные из наблюдаемых или предыдущих каналов и делать с ними что-либо, но не может изменить результат канала для следующего шага.

Map похож, но относится к первому типу канала, он принимает входные данные и должен возвращать выходные данные, которые можно использовать в следующем канале или окончательной подписке.

Finalize — это специальный канал, который делает то же, что и Tap, но после подписки. Хорошо, например, регистрировать окончательные результаты или отменить подписку после ее завершения.

CatchError – это конвейер, который изменяет результат, но вызывается только в том случае, если на предыдущем шаге возникла ошибка. Это используется, чтобы избежать необработанной ошибки, и вы должны вернуть наблюдаемое «по умолчанию» вместо ошибочного наблюдаемого (так что мы обрабатываем ошибку, и приложение не ломается).

Вы можете догадаться, когда у вашего наблюдаемого объекта возникла ошибка, если был запущен catchError, и обработать ее сразу, прежде чем она достигнет подписки.

Если этот пайп не запущен, результат считается без ошибок.

person Ignacio Bustos    schedule 27.06.2018
comment
Это не решает проблему. Функция (в конвейере), которая выполняется после всего, но зная, была ли ошибка или нет. - person JoniJnm; 29.10.2018
comment
Порядок выполнения Observable -> Pipes in order (except finalize) -> subscribe -> finalize Pipe с этим. Подписка получает то, что сделал catchError() в случае ошибки. Я объясню больше в ответ. - person Ignacio Bustos; 11.11.2018
comment
Если бы только настоящая документация для rxjs могла быть такой же простой, как этот ответ. Отличный пример и объяснение. - person Jessy; 26.02.2019

Вы можете использовать конкат

concat(
 yourObservable(),
 defer(() => {
  // do something on success
  return of('success');
 })
)

согласно документации, второй наблюдаемый объект будет подписан только в случае успешного завершения первого

person Melnychuk Roman    schedule 16.07.2019

Принятый ответ неверен. Почему? Потому что 'finalize' будет работать несмотря ни на что. См. случай Почему финализация отменена в RxJS?. Короче говоря, finalize будет работать независимо от того, есть ли ошибка или нет. Используйте переменную (вероятно, в закрытии), чтобы выяснить разницу:

let failed = false
source$.pipe(
   map(doSomethingFn),
   map(doAnotherThingFn),
   catchError(e => {failed = true; return throwError(e)}),
   finalize(() => {if(!failed)IwontRunIfErrorFn})
)
person tommyc38    schedule 03.04.2021
comment
Привет @tommyc38, вы правы насчет финализации, но это уже упоминалось в моем ответе, если вы проверите код, финализация уже имеет журнал консоли и строку с комментариями справа, объясняющую, когда это выполняется, в частности, упоминая, есть ли там или нет была ошибка. Но вы правы, я должен был оставить это более ясным. - person Ignacio Bustos; 12.04.2021