Como fazer o seu próprio operator RxJS 😮

João Henrique de Oliveira Júnior
TOTVS Developers
Published in
3 min readDec 15, 2020
Photo by fran innocenti on Unsplash

Se você conhece RxJS e o usa em seus códigos, você provavelmente sabe o quanto eles são úteis e poderosos, não é? Você pode ver a lista completa de operadores na página oficial do RxJS, lá eles possuem uma documentação eficiente separada em seções que tornam simples de entender e aprender.

Porém, pode ser que você queira gerar o seu próprio operador por uma razão específica que seu projeto necessite. Se for seu caso, é só continuar lendo esse tutorial prático.

Criando o seu operator

Atenção! Esse tutorial foi feito usando a versão 10.2.0 do Angular (:

A primeira coisa que você precisa entender é que os operadores são basicamente uma função. É simples mesmo. A grande diferença é o que eles recebem e devem retornar.

Vamos ver o exemplo abaixo:

const numbers = timer(3000, 1000);
const subscription = numbers.subscribe(x => console.log(x));
setTimeout(() => {
subscription.unsubscribe();
}, 10000);
/* Result console.log: 0, 1, 2, 3, 4, 5, 6 */

Relaxa, eu sei que você não vai usar algo do tipo nunca, eu sou terrível para criar exemplos. O observable criado via operador “timer” acima, emite depois de 3 segundos, um número a cada segundo. Eu coloquei uma função timeout também, apenas para fazer um unsubscribe após 10 segundos.

Se você quisesse fazer uma operação com esses números emitidos pelo observable, você poderia usar um pipe e um map por exemplo, certo? Eu vou dobrar cada valor agora:

const numbers = timer(3000, 1000);
const subscription = numbers
.pipe(
map(num: number) => num * 2)
)
.subscribe(x => console.log(x));
setTimeout(() => {
subscription.unsubscribe();
}, 10000);
/* Result console.log: 0, 2, 4, 6, 8, 10, 12*/

Massa, né? Eu te encorajo a sempre usar os operadores do RxJS, se você realmente não encontrar algo que lhe ajude (o que é bem raro). Então, é hora de implementar seu próprio pipe, como esse aqui:

function myDoubleOperator<T>(source: Observable<number>) {
return new Observable(subscriber => {
source.subscribe(
(num) => { subscriber.next(num * 2); },
error => { subscriber.error(error); },
() => { subscriber.complete(); }
);
});
}
const numbers = timer(3000, 1000);
const subscription = numbers
.pipe(myDoubleOperator)
.subscribe(x => console.log(x));
setTimeout(() => {
subscription.unsubscribe();
}, 10000);
/* Result console.log: 0, 2, 4, 6, 8, 10, 12 */

Observando o código acima, nós criamos uma função que retorna um novo Observable e é assim que ele funciona:

  • Se o observable anterior retornar um erro, ele retornar o erro.
  • Se o observable anterior completar, ele completa também.
  • Se o observable anterior emitir um número, então esse valor é dobrado antes do inscrito receber.

— Mas isso não é a mesma coisa que um simples map fez?

— Sim! Mas esse você mesmo codou!

Graças às features do Javascript, também é possível passar parâmetros para essa função:

function multiplyOperator(qtdToMultiply: number) {
return function add<T>(source: Observable<number>):
Observable<number> {
return new Observable(subscriber => {
source.subscribe(
(dado) => { subscriber.next(dado * qtdToMultiply); },
error => { subscriber.error(error); },
() => { subscriber.complete(); }
);
});
}
}
const numbers = timer(3000, 1000);
const subscription = numbers
.pipe(multiplyOperator(4))
.subscribe(x => console.log(x));
setTimeout(() => {
subscription.unsubscribe();
}, 10000);
/* Result console.log: 0, 4, 8, 12, 16, 20 */

Conclusão

Bem, padawan, agora os limites estão em sua imaginação. RxJS é rico e você deve aprendê-lo mais e mais. O Exemplo foi desenvolvido em Angular, Typescript e RxJS, mas você pode usar o RxJS sem o Angular também. Sem problemas.

Eu espero que tenha aprendido algo com esse post hoje. Até mais!

--

--

João Henrique de Oliveira Júnior
TOTVS Developers

Analista de sistemas na TOTVS. Bacharel e técnico em sistemas de informação. Ama a Deus, sua família, música e animais.