Observável finalmente na assinatura


105

De acordo com este artcle , onCompletee onErrorfunção do subscribesão mutuamente exclusivas.

Ou seja, os eventos onErrorou onCompletevão disparar no meu subscribe.
Eu tenho um bloco lógico que precisa ser executado se eu receber um erro ou terminar meu fluxo de informações com sucesso.

Procurei algo como finallyem python , mas tudo o que encontrei é finallyque precisa ser anexado ao observável que eu crio.

Mas quero fazer essa lógica apenas quando me inscrever e depois que o stream terminar, seja com sucesso ou com erro.

Alguma ideia?

Respostas:


130

A variante "pipable" atual deste operador é chamada finalize()(desde RxJS 6). O operador "patch" mais antigo e agora obsoleto foi chamado finally()(até RxJS 5.5).

Acho que a finalize()operadora está realmente correta. Você diz:

faça essa lógica apenas quando eu me inscrever e depois que o stream terminar

o que não é um problema, eu acho. Você pode ter um sourcee usar finalize()antes de assiná-lo, se desejar. Dessa forma, você não é obrigado a usar semprefinalize() :

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();

Isso imprime no console:

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

Janeiro de 2019: Atualizado para RxJS 6


1
Interessante que é o padrão oposto de Promessas, em que o finally()método é anexado primeiro, e a assinatura obrigatoriamente passa / falha.
BradGreens,

7
Sim, isso é muito ruim. Alguém poderia pensar que o finallybloco viria por último em seu código.
d512

Eu gostei do sistema de promessa do Angular JS ... Como d512 diz, eu esperava que "finalmente" fosse o último ... Não gosto nada disso ...
Sampgun

10
A partir do RXJS 5.5, "finalmente" não é mais um método observável. Em vez disso, use o operador "finalize": source.pipe (finalize (() => console.log ('Finalmente callback'))). Subscribe (...); github.com/ReactiveX/rxjs/blob/master/doc/pipeable-operators.md
Stevethemacguy

o problema com finalize é que espera por uma chamada "complete ()". e se você quiser um finalmente em cada emissão (se a emissão observável for bem-sucedida, faça a , se houver erro, faça b em vez disso. em ambos os casos, faça c )?
roberto tomás

65

A única coisa que funcionou para mim é esta

fetchData()
  .subscribe(
    (data) => {
       //Called when success
     },
    (error) => {
       //Called when error
    }
  ).add(() => {
       //Called when operation is complete (both success and error)
  });

26

Agora estou usando RxJS 5.5.7 em um aplicativo Angular e usar o finalizeoperador tem um comportamento estranho para o meu caso de uso, pois é disparado antes de retornos de chamada de sucesso ou erro.

Exemplo simples:

// 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);
      }
  );

Tive que usar o addmétodo na assinatura para realizar o que desejo. Basicamente, um finallyretorno de chamada após o sucesso ou erro de retorno de chamada. Como um try..catch..finallybloco ou Promise.finallymétodo.

Exemplo simples:

// 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.');
  });

Feliz em te ajudar.
pcasme
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.