[[oktatas:web:javascript|< JavaScript]] ====== JavaScript - RxJS ====== * **Szerző:** Sallai András * Copyright (c) 2023, Sallai András * Szerkesztve: 2023, 2024 * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC Attribution-Share Alike 4.0 International]] * Web: https://szit.hu ===== A megfigyelhetők ===== A megfigyelhetők angolul Observables. Az RxJS egy programozói könyvtár, amely lehetővé teszi adatok megfigyelését, aszinkron kódok könnyű kezelését. Az Observables, egy új primitív típus, ami lehetővé teszi, folyamok kezelését, amelyekre előfizethetünk, reagálhatunk új értékekre stb. A folyamokat kombinálhatjuk, amelyekből újabb folyamok készíthetők. A kérdés az ECMAScript szabványba bekerül-e az Observables? Amíg nincs benne az olyan könyvtárakat használhatjuk mint a RxJS. Az RxJS a **Reactive Extensions for JavaScript** szavakból alkotott betűszó, és egy olyan könyvtár, amit Observables-t biztosít JavaScript nyelven. A megfigyelők lusták. Addig nem termelnek adatokat, amíg fel nem iratkozunk azokra. * subscribe() - Feliratkozás az adatfolyamra. * unsubcribe() - Leiratkozás az adatfolyamról. ===== NodeJS projektben ===== npm init -y npm install rxjs npm install --save-dev lite-server Készítsünk egy bs-config.json fájlt, a lite-server számára, így használhatjuk a node_modules/rxjs/dist/bundles/ könyvtár állományait, úgy mintha egy könyvtárban lennének az src könyvtár állományaival: { "server": [ "src", "node_modules/rxjs/dist/bundles" ] } A HTML fájlban a rxjs.umd.min.js fájlt csatoljuk: RxJS példa

Valami

JavaScriptből, így elérhető az rxjs objektum, amelyből most az interval() függvényt használjuk: const { interval } = rxjs; /* 5 másodpercenként egy szám kibocsájtása */ const numbers = interval(5000); /* Feliratkozás az adatfolyamra */ numbers.subscribe({ next: res => { console.log(res); } }) Az Angular projektekben TypeScriptet használunk, így másként kell az importálást végrehajtani. ===== Take operátor ===== Az adatfolyam átalakítása. const { interval } = rxjs; const { take } = rxjs.operators; /* Az interval() egy Observable objektumot hoz létre, ami másodpercenként egy új számot bocsájt ki */ const numbers = interval(1000); /* A take operátorral korlátozzuk, hogy csak az első 5 értéket kapjuk meg. A teke() operátorokat a pipe() függvénnyel tudjuk használni. */ const fif = numbers.pipe( take(5) ) /* A subscribe() függvénnyel feliratkozunk az adatfolyamra. A paraméterben leírjuk, hogy mit történjen az érkező értékkel. */ fif.subscribe({ next: res => { console.log(res); } }) Eredmény: 0 1 2 3 4 ===== Map ===== A következő példában két operátorral is belenyúlunk az adatfolyamba. const { interval } = rxjs; const { take, map } = rxjs.operators; const numbers = interval(1000); /* A map(res => Date.now()) átalakítja az eredetileg kibocsájtott értéket, a kibocsájtás időbélyegét adja vissza. */ const fif = numbers.pipe( take(5), map( res => Date.now()) ) fif.subscribe({ next: res => { console.log(res); } }) 1681415031971 1681415032970 1681415033970 1681415034970 1681415035970 ===== From ===== A from() metódus segítségével egy tömbből megfigyelhető objektumot készítünk: const { from } = rxjs; const { map } = rxjs.operators; from([4, 8, 6, 2, 7]) .pipe(map(res => res * 2)) .subscribe({ next: res => { console.log(res); } }) * A from() függvény létrehoz egy Observable objektumot. * A map() függvény minden értéket felszoroz 2-vel. * A subscribe() függvénnyel feliratkozunk az eredményre. 8 16 12 4 14 ===== Az Observable metódusai ===== Ha feliratkozunk egy Observable objektum értékeire, három metódust kapunk vissza. Metódusok: * next * error * complete A három metódus leírása: * A next() akkor hajtódik végre, amikor megérkezik a következő adat. * A error() hiba esetén. * A complete() ha befejeződött az adatfolyam. const { from } = rxjs; from([1, 2, 3, 4, 5]) .subscribe({ next: res => { console.log(res); }, error: err => { console.log(err); }, complete: res => { console.log('kész') } }) Kimenet 1 2 3 4 5 kész ===== fromEvent ===== Feliratkozás eseményre. const { fromEvent } = rxjs; const goButton = document.querySelector('#goButton'); const observer = { next: res => { console.log(res); }, error: err => { console.log(err); }, complete: res => { console.log('kész') } } const observable = fromEvent(goButton, 'click'); observable.subscribe(observer); Leirtkozás const observable = fromEvent(goButton, 'click'); //Valamikor később, leiratkozhatunk az eseményről. const subscription = observable.subscribe(observer); subscription.unsubscribe(); ===== A Subject ===== A Subject egy speciális megfigyelő típus. Lehetővé teszi egyszerre több érték küldését. A következő példában két Observer van egy Subject-hez kapcsolva. const Subject = rxjs.Subject; sub = new Subject(); sub.subscribe({ next: res => console.log('A', res) }) sub.subscribe({ next: res => console.log('B', res) }) sub.next(1); sub.next(2); ===== A Promise és az Observable ===== Ha a Promise-on keresztül benyújtunk egy kérelmet, akkor biztosak lehetünk abban, hogy ugyanarra a kérésre nem érkezik több válasz. A Promise a feloldó függvénynek elsőnek átadott értékkel véget ért, figyelmen kívül hagyja a további hívásokat. Ezzel szemben az Observable lehetővé teszi több érték feloldását mindaddig, amíg meg nem hívjuk az observable.complete() függvényt. A Promise objektumok tervezésüknél fogva buzgók. A Promise konstruktor meghívása után azonnal elkezdi végrehajtani a megadott feladatot. Ezzel szemben az Observable addig nem hajtódik végre, amíg valaki fel nem iratkozik rá. A Promise kérés lemondását az ES6 még nem támogatja. Ha ilyet szeretnénk, a bluebird vagy az axios programozói könyvtárakat használhatjuk. Az Observable esetén eltárolhatjuk a feliratkozást egy Subscription objektumban, amin keresztül leiratkozhatunk az unsubscribe() függvénnyel. ===== Linkek ===== * https://codecraft.tv/courses/angular/reactive-programming-with-rxjs/observables-and-rxjs/ (2023) * https://dev.to/sagar/reactive-programming-in-javascript-with-rxjs-4jom (2023) * https://indepth.dev/posts/1114/learn-to-combine-rxjs-sequences-with-super-intuitive-interactive-diagrams (2023)