Наблюдаемый, наконец, при подписке

106

В соответствии с этим artcle , onCompleteи onErrorфункции subscribeявляются взаимоисключающими.

Значение либо onErrorили onCompleteсобытия будут стрелять в моих subscribe.
У меня есть логический блок, который должен выполняться независимо от того, получаю ли я сообщение об ошибке или успешно завершаю свой поток информации.

Я искал что-то вроде finallypython , но все, что я нашел, это то, finallyчто нужно прикрепить к наблюдаемому, которое я создаю.

Но я хочу использовать эту логику только при подписке и после завершения потока, успешно или с ошибкой.

Любые идеи?

Амир Туги
источник

Ответы:

135

Текущий «конвейерный» вариант этого оператора называется finalize()(начиная с RxJS 6). Был вызван более старый и устаревший оператор «patch» finally()(до RxJS 5.5).

Я думаю, что finalize()оператор на самом деле правильный. Ты говоришь:

делаю эту логику только тогда, когда я подписываюсь, и после того, как поток закончился

я думаю, это не проблема. Вы можете иметь сингл sourceи использовать finalize()перед подпиской на него, если хотите. Таким образом, вам не обязательно всегда использовать finalize():

let source = new Observable(observer => {
  observer.next(1);
  observer.error('error message');
  observer.next(3);
  observer.complete();
}).pipe(
  publish(),
);

source.pipe(
  finalize(() => console.log('Finally callback')),
).subscribe(
  value => console.log('#1 Next:', value),
  error => console.log('#1 Error:', error),
  () => console.log('#1 Complete')
);

source.subscribe(
  value => console.log('#2 Next:', value),
  error => console.log('#2 Error:', error),
  () => console.log('#2 Complete')
);

source.connect();

Это выводит на консоль:

#1 Next: 1
#2 Next: 1
#1 Error: error message
Finally callback
#2 Error: error message

Январь 2019: Обновлено для RxJS 6

Мартин
источник
1
Интересно то, что это своего рода паттерн, противоположный Promises, в том, что finally()метод добавляется первым, а подписка императивно заставляет пройти / не пройти.
BradGreens
7
Ага, это очень плохо. Можно было бы подумать, что finallyблок будет последним в вашем коде.
d512 08
Мне понравилась система обещаний Angular JS ... Как говорит d512, я ожидал, что "наконец-то" будет последним ...
Совсем
10
Начиная с RXJS 5.5, "finally" больше не является наблюдаемым методом. Вместо этого используйте оператор «finalize»: source.pipe (finalize (() => console.log ('Наконец обратный вызов'))). Subscribe (...); github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md
Stevethemacguy 06
проблема с finalize в том, что он ждет вызова «complete ()». что, если вы хотите, наконец, для каждой эмиссии (если наблюдаемая эмиссия успешна, сделайте a , если она ошиблась, сделайте b вместо этого ... в обоих случаях сделайте c )?
Роберто Томас,
68

Единственное, что у меня сработало, это

fetchData()
  .subscribe(
    (data) => {
       //Called when success
     },
    (error) => {
       //Called when error
    }
  ).add(() => {
       //Called when operation is complete (both success and error)
  });
Хари Дас
источник
26

Теперь я использую RxJS 5.5.7 в приложении Angular, и finalizeоператор using имеет странное поведение для моего варианта использования, поскольку он запускается до успешных или ошибочных обратных вызовов.

Простой пример:

// Simulate an AJAX callback...
of(null)
  .pipe(
    delay(2000),
    finalize(() => {
      // Do some work after complete...
      console.log('Finalize method executed before "Data available" (or error thrown)');
    })
  )
  .subscribe(
      response => {
        console.log('Data available.');
      },
      err => {
        console.error(err);
      }
  );

Мне пришлось использовать addмедход в подписке, чтобы выполнить то, что я хочу. В основном finallyобратный вызов выполняется после успешного или ошибочного обратного вызова. Как try..catch..finallyблок или Promise.finallyметод.

Простой пример:

// Simulate an AJAX callback...
of(null)
  .pipe(
    delay(2000)
  )
  .subscribe(
      response => {
        console.log('Data available.');
      },
      err => {
        console.error(err);
      }
  );
  .add(() => {
    // Do some work after complete...
    console.log('At this point the success or error callbacks has been completed.');
  });
pcasme
источник
Рад помочь вам.
pcasme