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?

Amir Tugi
fonte

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

Martin
fonte
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)
  });
Hari Das
fonte
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.');
  });
pcasme
fonte
Feliz em te ajudar.
pcasme