https://github.com/artodeschini/rxjs-school
javascript node rxjs
https://github.com/artodeschini/rxjs-school
Last synced: about 2 months ago
JSON representation
javascript node rxjs
- Host: GitHub
- URL: https://github.com/artodeschini/rxjs-school
- Owner: artodeschini
- Created: 2024-03-02T01:30:20.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-05-14T22:34:40.000Z (about 2 years ago)
- Last Synced: 2025-03-06T05:45:18.763Z (over 1 year ago)
- Language: JavaScript
- Size: 123 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# rxjs
## guia de apredizagem com rxjs
[link original](https://github.com/kaikcreator/rxjs-school)
## site oficial
[rxjs](https://rxjs.dev/)
## para executar o projeto com webpack
```bash
npm start
```
## criar Observable com create ou new
```bash
git checkout dev/02-subscriptions
```
```js
// versao legada
// const hello = Observable.create(function(observer) {
//const forma com ts hello = new Observable((observer: Observer) => {
const hello = new Observable((observer) => {
observer.next('Hello');
setTimeout(()=>{
observer.next('World');
observer.complete();
}, 2000);
// observer.complete(); nunca ira escrever o segundo aqui
});
const observer = {
next: e => displayLog(e),
error: err => console.error(`[Erro] ${err}`),
complete: () => displayLog("Completou!!!")
}
const subscribe1 = hello.subscribe(observer);// evt => displayLog(evt));
const subscribe2 = hello.subscribe(observer);// evt => displayLog(evt));
// remove a subscricao cancelando as d+ execucoes dos proximos
subscribe1.unsubscribe();
```
## Observeble com from
```bash
git checkout dev/03-from
```
```js
const myArray = [0,1,2,3,4,5,6,7];
const myString = "Hello World";
const myPromise = new Promise(resolve => setTimeout(() => {
resolve("Minha Promise!")
}, 2000));
const observable1 = from(myArray);
const observable2 = from(myString);
const observable3 = from(myPromise);
const subscribe1 = observable1.subscribe(v => displayLog(v));
const subscribe2 = observable2.subscribe(v => displayLog(v));
const subscribe3 = observable3.subscribe(v => displayLog(v));
```
## criando Observable com of e range
```bash
git checkout dev/04-of-and-range
```
```js
const source1 = of(1,2,3,4,5,6,7,8,9);
const source2 = of(
[1,2,3],
"Ola Mundo",
{comida: "pasto", bebida: "agua"},
function myFunction() {
return "uma funcao";
}
);
const source3 = range(2, 9);
const subscribe1 = source1.subscribe(data => displayLog(data));
const subscribe2 = source2.subscribe(data => displayLog(data));
const subscribe3 = source3.subscribe(data => displayLog(data));
```
## criando Observable com interval e controlando com timer
```bash
git checkout dev/05-interval-and-timer
```
```js
const source1 = interval(500);
const subscription1 = source1.subscribe(v => displayLog(v));
// setTimeout(() => subscription.unsubscribe(), 3000);
timer(3000).subscribe(() => subscription1.unsubscribe());
const source2 = timer(4000, 100);
const subscription2 = source2.subscribe(v => displayLog(`2 -- ${v}`));
timer(6000).subscribe(() => subscription2.unsubscribe());
```
## observando enventos de interface
```bash
git checkout dev/06-fromevent
```
```js
const acaoBotao = document.getElementById("action-btn");
const source1 = fromEvent(acaoBotao, "click");
source1.subscribe(event => {
displayLog(`click event at posição (${event.x}, ${event.y})`);
});
const source2 = fromEvent(document, "mousemove");
source2.subscribe(event => {
console.log(event);
});
```
## operadores mapTo map e filter
```bash
git checkout dev/07-mapto-map-and-filter
```
```js
const grid = document.getElementById('grid');
const click$ = fromEvent(grid, 'click').pipe(
// mapTo("CLICK") // fuciona mas é deprecated
// map(() => "CLICK") // ao inves de usar mapTo use assim
// map(e => [e.offsetX, e.offsetY]) // cada quadrado tem 50 px para pegar a posicao
map(e => [
Math.floor(e.offsetX / 50),
Math.floor(e.offsetY / 50)
]),
filter(v => (v[0] + v[1]) % 2 != 0) // pega só os eventos nas casas cinzas
);
const subscribe = click$.subscribe(e => { displayLog(e) });
```
## operador tap
Mostra uma previa sem alterar o conteudo
```bash
git checkout dev/08-tap
```
```js
const grid = document.getElementById('grid');
const click$ = fromEvent(grid, 'click').pipe(
tap(antes => console.log(`antes original ${antes} e ${JSON.stringify(antes)}`)),
map(val => [
// pega as coordenadas ma grid cada celula tem 50px x 50px
Math.floor(val.offsetX/50),
Math.floor(val.offsetY/50)
]),
tap(depois => console.log(`depois ${depois}`))
);
const subscription = click$.subscribe(data => displayLog(data));
```
## limitando eventos com first, take e takeWile
```bash
git checkout dev/09-first-take-takewhile
```
```js
export default () => {
/** start coding */
const grid = document.getElementById('grid');
const click$ = fromEvent(grid, 'click').pipe(
map(val => [
Math.floor(val.offsetX/50),
Math.floor(val.offsetY/50)
]),
//first(v => v[0]> 3) // limita o numero de eventos no caso aqui
//take(4) // serao monitorados 4 eventos apos serao discartados
takeWhile(([col, row]) => col > 3)
);
const subscription = click$.subscribe(data => displayLog(data));
/** end coding */
}
```
## operadores last takeLast e skip
```bash
git checkout dev/10-last-takelast-skip
```
```js
// operador last
export default () => {
/** start coding */
const grid = document.getElementById('grid');
const click$ = fromEvent(grid, 'click').pipe(
map(val => [
Math.floor(val.offsetX/50),
Math.floor(val.offsetY/50)
]),
takeWhile( ([col, row]) => col > 3 ),
/tap(v => console.log(`${v} é valido em operador takeWhile`)),
// ultimo evento
last()
);
const subscription = click$.subscribe(data => displayLog(data));
/** end coding */
}
```
```js
// operador takeLast
export default () => {
/** start coding */
const grid = document.getElementById('grid');
const click$ = fromEvent(grid, 'click').pipe(
map(val => [
Math.floor(val.offsetX/50),
Math.floor(val.offsetY/50)
]),
takeWhile( ([col, row]) => col > 3 ),
tap(v => console.log(`${v} é valido em operador takeWhile`)),
// ultimo n envetos
takeLast(3) // tres eventos
);
const subscription = click$.subscribe(data => displayLog(data));
/** end coding */
}
```
```js
// operador skip
export default () => {
/** start coding */
const grid = document.getElementById('grid');
const click$ = fromEvent(grid, 'click').pipe(
map(val => [
Math.floor(val.offsetX/50),
Math.floor(val.offsetY/50)
]),
tap(v => console.log(`${v} coordenada`)),
skip(5) // pula 5 eventos
);
const subscription = click$.subscribe(data => displayLog(data));
/** end coding */
}
```
## git checkout dev/11-reduce-scan
The difference is an observable created with `scan` will emit on each source emission, whereas `reduce` will emit `only once` on completion.
```js
import { displayLog } from './utils';
import { fromEvent } from 'rxjs';
import { map, takeWhile, tap, reduce } from 'rxjs/operators';
export default () => {
/** start coding */
const grid = document.getElementById('grid');
const click$ = fromEvent(grid, 'click').pipe(
map(val => [
Math.floor(val.offsetX/50),
Math.floor(val.offsetY/50)
]),
takeWhile( ([col, row]) => col != 0 ),
tap(val => console.log(`cell: [${val}]`)),
/* reduce((acumulados, current) => {
return {
clicks: acumulados.clicks + 1,
cells: [... acumulados.cells, current]
}
},
{clicks: 0, cells: []} // na primeira passada o acumulado assume esse objeto
) // fim reduce */
scan((acumulados, current) => {
return {
clicks: acumulados.clicks + 1,
cells: [... acumulados.cells, current]
}
},
{clicks: 0, cells: []} // na primeira passada o acumulado assume esse objeto
) // fim scan
);
const subscription = click$.subscribe(data => displayLog(`${data.clicks} clicks: ${JSON.stringify(data.cells)}`));
/** end coding */
}
```
## dev/12-startwith-endwidth
Faz algo antes com `startwith` e depois `endwidth` do observeble
```js
import { displayLog } from './utils';
import { fromEvent } from 'rxjs';
import { endWith, map, startWith, takeWhile, tap } from 'rxjs/operators';
export default () => {
/** start coding */
const grid = document.getElementById('grid');
const click$ = fromEvent(grid, 'click').pipe(
map(val => [
Math.floor(val.offsetX/50),
Math.floor(val.offsetY/50)
]),
takeWhile( ([col, row]) => col != 0 ),
tap(val => console.log(`cell: [${val}]`)),
startWith('Grid dimensoes 10 x 10'),
endWith("Game fim", "bye")
);
const subscription = click$.subscribe(data => displayLog(data));
/** end coding */
}
```
## operador distict diferencia um evento do outro
```js
import { fromEvent } from 'rxjs';
import { map, takeWhile, tap, distinct, distinctUntilChanged } from 'rxjs/operators';
export default () => {
/** start coding */
const grid = document.getElementById('grid');
const click$ = fromEvent(grid, 'click').pipe(
map(val => [
Math.floor(val.offsetX/50),
Math.floor(val.offsetY/50)
]),
takeWhile( ([col, row]) => col != 0 ),
tap(val => console.log(`cell: [${val}]`)),
//map(([col, row]) => col+row),
tap(val => console.log('sum of col + row is:', val)),
distinct(([col, row]) => `${col} - ${row}`),
/*distinctUntilChanged((c1, c2) =>
(c1[0] == c2[0]) && (c1[1] == c2[2])
) */
);
const subscription = click$.subscribe(data => displayLog(data));
/** end coding */
}
```
## exemplo com parwise
```bash
git checkout dev/14-pairwise
```
```js
import { fromEvent } from 'rxjs';
import { map, tap, pairwise } from 'rxjs/operators';
export default () => {
/** start coding */
const progressBar = document.getElementById('progress-bar');
const docElement = document.documentElement;
const updateProgressBar = (percentage) => {
progressBar.style.width = `${percentage}%`;
}
//observable that returns scroll (from top) on scroll events
const scroll$ = fromEvent(document, 'scroll').pipe(
map(() => docElement.scrollTop),
tap(evt => console.log("[scroll]: ", evt)),
pairwise(),
tap(([previous, current]) =>{
updateDisplay(current > previous ? 'DESC' : 'ASC');
}),
map(([previous, current]) => current)
);
//observable that returns the amount of page scroll progress
const scrollProgress$ = scroll$.pipe(
map(evt => {
const docHeight = docElement.scrollHeight - docElement.clientHeight;
return (evt / docHeight) * 100;
})
)
//subscribe to scroll progress to paint a progress bar
const subscription = scrollProgress$.subscribe(updateProgressBar);
/** end coding */
}
```
## exemplo com subject e BehaviorSubject
Ao inves de usar shared como operador posso ou devo usar Subject, BehaviorSubject
O `Subject` é um tipo de `Observable`.
A maneira de diferenciar um `Subject` de um `BehaviorSubject` é: O `Subject` não têm valor inicial. Os `Subscribers` somente serão notificados e receberão eventos/valores após a realização da assinatura – ou seja, os `Subscribers` não receberão o último valor emitido no ato da assinatura.
```bash
git chekout dev/16-subject
```
```js
import { fromEvent, Subject, BehaviorSubject } from 'rxjs';
import { map, tap } from 'rxjs/operators';
export default () => {
/** start coding */
const progressBar = document.getElementById('progress-bar');
const docElement = document.documentElement;
//function to update progress bar width on view
const updateProgressBar = (percentage) => {
progressBar.style.width = `${percentage}%`;
}
//observable that returns scroll (from top) on scroll events
const scroll$ = fromEvent(document, 'scroll').pipe(
map(() => docElement.scrollTop),
tap(evt => console.log("[scroll]: ", evt))
);
//observable that returns the amount of page scroll progress
const scrollProgress$ = scroll$.pipe(
map(evt => {
const docHeight = docElement.scrollHeight - docElement.clientHeight;
return (evt / docHeight) * 100;
})
);
//const scrollProgressHot$ = new Subject();
const scrollProgressHot$ = new BehaviorSubject(0);
scrollProgress$.subscribe(scrollProgressHot$);
//subscribe to scroll progress to paint a progress bar
const subscription = scrollProgressHot$.subscribe(updateProgressBar);
//subscribe to display scroll progress percentage
const subscription2 = scrollProgressHot$.subscribe(
val => updateDisplay(`${ Math.floor(val) } %`)
);
//scrollProgressHot$.next(0);
console.log("scroll initial state: ", scrollProgressHot$.value);
/** end coding */
}
```