{"id":20550821,"url":"https://github.com/artodeschini/rxjs-school","last_synced_at":"2026-04-20T00:02:00.620Z","repository":{"id":225430219,"uuid":"765967574","full_name":"artodeschini/rxjs-school","owner":"artodeschini","description":"javascript node rxjs","archived":false,"fork":false,"pushed_at":"2024-05-14T22:34:40.000Z","size":126,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-06T05:45:18.763Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/artodeschini.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-02T01:30:20.000Z","updated_at":"2024-05-14T22:34:43.000Z","dependencies_parsed_at":"2024-05-15T13:57:14.943Z","dependency_job_id":"8ae07bf7-39e5-4d02-976c-12df8175d9c9","html_url":"https://github.com/artodeschini/rxjs-school","commit_stats":null,"previous_names":["artodeschini/rxjs-school"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/artodeschini/rxjs-school","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artodeschini%2Frxjs-school","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artodeschini%2Frxjs-school/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artodeschini%2Frxjs-school/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artodeschini%2Frxjs-school/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/artodeschini","download_url":"https://codeload.github.com/artodeschini/rxjs-school/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/artodeschini%2Frxjs-school/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32027234,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T20:23:30.271Z","status":"online","status_checked_at":"2026-04-19T02:00:07.110Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T02:27:31.467Z","updated_at":"2026-04-20T00:02:00.479Z","avatar_url":"https://github.com/artodeschini.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# rxjs\n\n## guia de apredizagem com rxjs\n\n[link original](https://github.com/kaikcreator/rxjs-school)\n\n## site oficial\n\n[rxjs](https://rxjs.dev/)\n\n## para executar o projeto com webpack\n\n```bash\nnpm start\n```\n\n## criar Observable com create ou new\n\n```bash\ngit checkout dev/02-subscriptions\n```\n\n```js\n // versao legada\n // const hello = Observable.create(function(observer) {\n    //const forma com ts hello = new Observable((observer: Observer\u003cstring\u003e) =\u003e {        \n    const hello = new Observable((observer) =\u003e {\n        observer.next('Hello');\n        setTimeout(()=\u003e{\n            observer.next('World');\n            observer.complete();\n        }, 2000);\n\n        // observer.complete(); nunca ira escrever o segundo aqui\n    });\n\n    const observer = {\n        next: e =\u003e displayLog(e),\n        error: err =\u003e console.error(`[Erro] ${err}`),\n        complete: () =\u003e displayLog(\"Completou!!!\")\n    }\n    \n    const subscribe1 = hello.subscribe(observer);// evt =\u003e displayLog(evt));\n    const subscribe2 = hello.subscribe(observer);// evt =\u003e displayLog(evt));\n    // remove a subscricao cancelando as d+ execucoes dos proximos\n    subscribe1.unsubscribe();\n```\n\n## Observeble com from\n\n```bash\ngit checkout dev/03-from\n```\n\n```js\nconst myArray = [0,1,2,3,4,5,6,7];\n    const myString = \"Hello World\";\n    const myPromise = new Promise(resolve =\u003e setTimeout(() =\u003e {\n        resolve(\"Minha Promise!\")\n    }, 2000));\n\n    const observable1 = from(myArray);\n    const observable2 = from(myString);\n    const observable3 = from(myPromise);\n\n    const subscribe1 = observable1.subscribe(v =\u003e displayLog(v));\n    const subscribe2 = observable2.subscribe(v =\u003e displayLog(v));\n    const subscribe3 = observable3.subscribe(v =\u003e displayLog(v));\n```\n\n## criando Observable com of e range\n\n```bash\ngit checkout dev/04-of-and-range\n```\n\n```js\nconst source1 = of(1,2,3,4,5,6,7,8,9);\n    const source2 = of(\n        [1,2,3],\n        \"Ola Mundo\",\n        {comida: \"pasto\", bebida: \"agua\"},\n        function myFunction() {\n            return \"uma funcao\";\n        }\n    );\n    const source3 = range(2, 9);\n    \n    const subscribe1 = source1.subscribe(data =\u003e displayLog(data));\n    const subscribe2 = source2.subscribe(data =\u003e displayLog(data));\n    const subscribe3 = source3.subscribe(data =\u003e displayLog(data));\n```\n\n## criando Observable com interval e controlando com timer\n\n```bash\ngit checkout dev/05-interval-and-timer\n```\n\n```js\n    const source1 = interval(500);\n    const subscription1 = source1.subscribe(v =\u003e displayLog(v));\n\n    // setTimeout(() =\u003e subscription.unsubscribe(), 3000);\n    timer(3000).subscribe(() =\u003e subscription1.unsubscribe());\n\n    const source2 = timer(4000, 100);\n    const subscription2 = source2.subscribe(v =\u003e displayLog(`2 -- ${v}`));\n    \n    timer(6000).subscribe(() =\u003e subscription2.unsubscribe());\n```\n\n## observando enventos de interface\n\n```bash\ngit checkout dev/06-fromevent\n```\n\n```js\n    const acaoBotao = document.getElementById(\"action-btn\");\n\n    const source1 = fromEvent(acaoBotao, \"click\");\n\n    source1.subscribe(event =\u003e {\n        displayLog(`click event at posição (${event.x}, ${event.y})`);\n    });\n\n    const source2 = fromEvent(document, \"mousemove\");\n\n    source2.subscribe(event =\u003e {\n        console.log(event);\n    });\n```\n\n## operadores mapTo map e filter\n\n```bash\ngit checkout dev/07-mapto-map-and-filter\n```\n\n```js\n    const grid = document.getElementById('grid');\n\n    const click$ = fromEvent(grid, 'click').pipe(\n        // mapTo(\"CLICK\") // fuciona mas é deprecated\n        // map(() =\u003e \"CLICK\") // ao inves de usar mapTo use assim\n        // map(e =\u003e [e.offsetX, e.offsetY]) // cada quadrado tem 50 px para pegar a posicao\n        map(e =\u003e [\n            Math.floor(e.offsetX / 50),\n            Math.floor(e.offsetY / 50)\n        ]),\n        filter(v =\u003e (v[0] + v[1]) % 2 != 0) // pega só os eventos nas casas cinzas\n    );\n    const subscribe = click$.subscribe(e =\u003e { displayLog(e) });\n```\n\n## operador tap\n\nMostra uma previa sem alterar o conteudo\n\n```bash\ngit checkout dev/08-tap\n```\n\n```js\n    const grid = document.getElementById('grid');\n    const click$ = fromEvent(grid, 'click').pipe(\n        tap(antes =\u003e console.log(`antes original ${antes} e ${JSON.stringify(antes)}`)),\n        map(val =\u003e [\n            // pega as coordenadas ma grid cada celula tem 50px x 50px\n            Math.floor(val.offsetX/50), \n            Math.floor(val.offsetY/50)\n        ]),\n        tap(depois =\u003e console.log(`depois ${depois}`))\n    );\n\n    const subscription = click$.subscribe(data =\u003e displayLog(data));\n```\n\n## limitando eventos com first, take e takeWile\n\n```bash\ngit checkout dev/09-first-take-takewhile\n```\n\n```js\nexport default () =\u003e {\n    /** start coding */\n    const grid = document.getElementById('grid');\n    const click$ = fromEvent(grid, 'click').pipe(\n        map(val =\u003e [ \n            Math.floor(val.offsetX/50), \n            Math.floor(val.offsetY/50)\n        ]),\n        //first(v =\u003e v[0]\u003e 3) // limita o numero de eventos no caso aqui \n        //take(4) // serao monitorados 4 eventos apos serao discartados\n        takeWhile(([col, row]) =\u003e col \u003e 3)\n    );\n\n    const subscription = click$.subscribe(data =\u003e displayLog(data));\n\n    /** end coding */\n}\n```\n\n## operadores last takeLast e skip\n\n```bash\ngit checkout dev/10-last-takelast-skip\n```\n\n```js\n// operador last\nexport default () =\u003e {\n    /** start coding */\n    const grid = document.getElementById('grid');\n    const click$ = fromEvent(grid, 'click').pipe(\n        map(val =\u003e [ \n            Math.floor(val.offsetX/50), \n            Math.floor(val.offsetY/50)\n        ]),\n        takeWhile( ([col, row]) =\u003e col \u003e 3 ),\n        /tap(v =\u003e console.log(`${v} é valido em operador takeWhile`)),\n        // ultimo evento\n        last()\n    );\n\n    const subscription = click$.subscribe(data =\u003e displayLog(data));\n\n    /** end coding */\n}\n```\n\n```js\n// operador takeLast\nexport default () =\u003e {\n    /** start coding */\n    const grid = document.getElementById('grid');\n    const click$ = fromEvent(grid, 'click').pipe(\n        map(val =\u003e [ \n            Math.floor(val.offsetX/50), \n            Math.floor(val.offsetY/50)\n        ]),\n        takeWhile( ([col, row]) =\u003e col \u003e 3 ),\n        tap(v =\u003e console.log(`${v} é valido em operador takeWhile`)),\n        // ultimo n envetos\n        takeLast(3) // tres eventos\n    );\n\n    const subscription = click$.subscribe(data =\u003e displayLog(data));\n\n    /** end coding */\n}\n```\n\n```js\n// operador skip\nexport default () =\u003e {\n    /** start coding */\n    const grid = document.getElementById('grid');\n    const click$ = fromEvent(grid, 'click').pipe(\n        map(val =\u003e [ \n            Math.floor(val.offsetX/50), \n            Math.floor(val.offsetY/50)\n        ]),\n        tap(v =\u003e console.log(`${v} coordenada`)),\n        skip(5) // pula 5 eventos\n    );\n\n    const subscription = click$.subscribe(data =\u003e displayLog(data));\n\n    /** end coding */\n}\n```\n\n## git checkout dev/11-reduce-scan\n\nThe difference is an observable created with `scan` will emit on each source emission, whereas `reduce` will emit `only once` on completion.\n\n```js\nimport { displayLog } from './utils';\nimport { fromEvent } from 'rxjs';\nimport { map, takeWhile, tap, reduce } from 'rxjs/operators';\n\nexport default () =\u003e {\n    /** start coding */\n    const grid = document.getElementById('grid');\n    const click$ = fromEvent(grid, 'click').pipe(\n        map(val =\u003e [ \n            Math.floor(val.offsetX/50), \n            Math.floor(val.offsetY/50)\n        ]),\n        takeWhile( ([col, row]) =\u003e col != 0 ),\n        tap(val =\u003e console.log(`cell: [${val}]`)),\n        /* reduce((acumulados, current) =\u003e {\n            return {\n                clicks: acumulados.clicks + 1,\n                cells: [... acumulados.cells, current]\n            }\n        }, \n        {clicks: 0, cells: []} // na primeira passada o acumulado assume esse objeto\n        ) // fim reduce */\n        scan((acumulados, current) =\u003e {\n            return {\n                clicks: acumulados.clicks + 1,\n                cells: [... acumulados.cells, current]\n            }\n        }, \n        {clicks: 0, cells: []} // na primeira passada o acumulado assume esse objeto\n        ) // fim scan\n    );\n\n    const subscription = click$.subscribe(data =\u003e displayLog(`${data.clicks} clicks: ${JSON.stringify(data.cells)}`));\n\n    /** end coding */\n}\n```\n\n## dev/12-startwith-endwidth\n\nFaz algo antes com `startwith` e depois `endwidth` do observeble\n\n```js\nimport { displayLog } from './utils';\nimport { fromEvent } from 'rxjs';\nimport { endWith, map, startWith, takeWhile, tap } from 'rxjs/operators';\n\nexport default () =\u003e {\n    /** start coding */\n    const grid = document.getElementById('grid');\n    const click$ = fromEvent(grid, 'click').pipe(\n        map(val =\u003e [ \n            Math.floor(val.offsetX/50), \n            Math.floor(val.offsetY/50)\n        ]),\n        takeWhile( ([col, row]) =\u003e col != 0 ),\n        tap(val =\u003e console.log(`cell: [${val}]`)),\n        startWith('Grid dimensoes 10 x 10'),\n        endWith(\"Game fim\",  \"bye\")\n    );\n\n    const subscription = click$.subscribe(data =\u003e displayLog(data));\n\n    /** end coding */\n}\n```\n\n## operador distict diferencia um evento do outro\n\n```js\nimport { fromEvent } from 'rxjs';\nimport { map, takeWhile, tap, distinct, distinctUntilChanged } from 'rxjs/operators';\n\nexport default () =\u003e {\n    /** start coding */\n    const grid = document.getElementById('grid');\n    const click$ = fromEvent(grid, 'click').pipe(\n        map(val =\u003e [ \n            Math.floor(val.offsetX/50), \n            Math.floor(val.offsetY/50)\n        ]),\n        takeWhile( ([col, row]) =\u003e col != 0 ),\n        tap(val =\u003e console.log(`cell: [${val}]`)),\n        //map(([col, row]) =\u003e col+row),\n        tap(val =\u003e console.log('sum of col + row is:', val)),\n        distinct(([col, row]) =\u003e `${col} - ${row}`),\n        /*distinctUntilChanged((c1, c2) =\u003e\n            (c1[0] == c2[0]) \u0026\u0026 (c1[1] == c2[2])\n        ) */\n\n    );\n\n    const subscription = click$.subscribe(data =\u003e displayLog(data));\n\n    /** end coding */\n}\n```\n\n## exemplo com parwise\n\n```bash\ngit checkout dev/14-pairwise\n```\n\n```js\nimport { fromEvent } from 'rxjs';\nimport { map, tap, pairwise } from 'rxjs/operators';\n\nexport default () =\u003e {\n    /** start coding */\n    const progressBar = document.getElementById('progress-bar');\n    const docElement = document.documentElement;\n    const updateProgressBar = (percentage) =\u003e {\n        progressBar.style.width = `${percentage}%`;\n    }\n\n    //observable that returns scroll (from top) on scroll events\n    const scroll$ = fromEvent(document, 'scroll').pipe(\n        map(() =\u003e docElement.scrollTop),\n        tap(evt =\u003e console.log(\"[scroll]: \", evt)),\n        pairwise(),\n        tap(([previous, current]) =\u003e{\n            updateDisplay(current \u003e previous ? 'DESC' : 'ASC');\n        }),\n        map(([previous, current]) =\u003e current)\n    );\n\n    //observable that returns the amount of page scroll progress\n    const scrollProgress$ = scroll$.pipe(\n        map(evt =\u003e {\n            const docHeight = docElement.scrollHeight - docElement.clientHeight;\n            return (evt / docHeight) * 100;\n        })\n    )\n\n    //subscribe to scroll progress to paint a progress bar\n    const subscription = scrollProgress$.subscribe(updateProgressBar);\n\n    /** end coding */\n}\n```\n\n## exemplo com subject e BehaviorSubject\n\nAo inves de usar shared como operador posso ou devo usar Subject, BehaviorSubject\n\nO `Subject` é um tipo de `Observable`.\nA 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.\n\n```bash\ngit chekout dev/16-subject\n```\n\n```js\nimport { fromEvent, Subject, BehaviorSubject } from 'rxjs';\nimport { map, tap } from 'rxjs/operators';\n\nexport default () =\u003e {\n    /** start coding */\n\n    const progressBar = document.getElementById('progress-bar');\n    const docElement = document.documentElement;\n\n    //function to update progress bar width on view\n    const updateProgressBar = (percentage) =\u003e {\n        progressBar.style.width = `${percentage}%`;\n    }\n\n    //observable that returns scroll (from top) on scroll events\n    const scroll$ = fromEvent(document, 'scroll').pipe(\n        map(() =\u003e docElement.scrollTop),\n        tap(evt =\u003e console.log(\"[scroll]: \", evt))\n    );\n\n    //observable that returns the amount of page scroll progress\n    const scrollProgress$ = scroll$.pipe(\n        map(evt =\u003e {\n            const docHeight = docElement.scrollHeight - docElement.clientHeight;\n            return (evt / docHeight) * 100;\n        })\n    );\n\n    //const scrollProgressHot$ = new Subject();\n    const scrollProgressHot$ = new BehaviorSubject(0);\n    scrollProgress$.subscribe(scrollProgressHot$);\n\n    //subscribe to scroll progress to paint a progress bar\n    const subscription = scrollProgressHot$.subscribe(updateProgressBar);\n\n    //subscribe to display scroll progress percentage\n    const subscription2 = scrollProgressHot$.subscribe(\n        val =\u003e updateDisplay(`${ Math.floor(val) } %`)\n    );\n\n    //scrollProgressHot$.next(0);\n    console.log(\"scroll initial state: \", scrollProgressHot$.value);\n\n    /** end coding */\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartodeschini%2Frxjs-school","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fartodeschini%2Frxjs-school","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fartodeschini%2Frxjs-school/lists"}