{"id":36774,"date":"2019-10-31T22:13:44","date_gmt":"2019-10-31T19:13:44","guid":{"rendered":"https:\/\/prohoster.info\/blog\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\/"},"modified":"2019-10-31T22:13:44","modified_gmt":"2019-10-31T19:13:44","slug":"asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","status":"publish","type":"post","link":"https:\/\/prohoster.info\/et\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","title":{"rendered":"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Tere k\u00f5igile. Siin on Omelnitski Sergei. Hiljuti viisin l\u00e4bi voogedastuse reaktiivprogrammeerimise kohta, kus r\u00e4\u00e4kisin as\u00fcnkroonsusest JavaScriptis. T\u00e4na tahaksin selle materjali kokku v\u00f5tta. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/11acf6af8328d3deb6f0ce48e813efb7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Kuid enne, kui alustame p\u00f5hiteemat, peame tegema sissejuhatuse. Niisiis, alustame m\u00e4\u00e4ratlemisest: mis on virn ja j\u00e4rjekord?<br \/>\n<strong>Virn <\/strong>on kogum, mille elemendid saavad p\u00f5hinedes \"viimane sisse, first out\" LIFO<br \/>\n<strong>J\u00e4rjekord <\/strong>on kogum, mille elemendid saavad p\u00f5hinedes \"esimene sisse, esimene v\u00e4lja\" FIFO<\/p>\n<p><\/p>\n<p>Selge, j\u00e4tkame. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a7d64d1c74f37b463869dd57b96c9d0e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>JavaScript on \u00fchetine programmeerimiskeel. See t\u00e4hendab, et seal on ainult \u00fcks teostusniit ja \u00fcks virn, kuhu funktsioonid pandakse t\u00e4itmiseks j\u00e4rjekorda. Seega saab JavaScript korraga teostada ainult \u00fchte operatsiooni, teised operatsioonid peavad oma j\u00e4rjekorda ootama virnas, kuni neid kutsutakse. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Kutsumisvirn<\/strong> on andmestruktuur, mis lihtsustatult \u00f6eldes salvestab teavet selle kohta, kus me programmis asume. Kui me liigume funktsiooni, paneme selle kirje virna \u00fclempoolsesse ossa. Kui me funktsioonist tagasi tuleme, t\u00f5mbame virnast k\u00f5ige \u00fclemise elemendi ja j\u00f5uame sinna, kust seda funktsiooni kutsuti. See on k\u00f5ik, mida virn suudab. N\u00fc\u00fcd on v\u00e4ga huvitav k\u00fcsimus. Kuidas siis t\u00f6\u00f6tab as\u00fcnkroonsus JavaScriptis?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a29fd1dd3de06fb203c7dd14bda30548.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tegelikult on peale virna brauserites olemas ka eriline j\u00e4rjekord, kus t\u00f6\u00f6tab nn WebAPI. Funktsioonid sellest j\u00e4rjekorrast t\u00e4idetakse j\u00e4rjestikku ainult p\u00e4rast seda, kui virn on t\u00e4ielikult t\u00fchjaks tehtud. Alles p\u00e4rast seda paigutatakse need j\u00e4rjekorrast virna t\u00e4itmiseks. Kui virnas on v\u00e4hemalt \u00fcks element, siis nad ei saa virna siseneda. Just seet\u00f5ttu on funktsioonide kutsumine ajavahemiku j\u00e4rgi tihti ajaliselt ebat\u00e4pne, kuna funktsioon ei saa p\u00e4\u00e4seda j\u00e4rjekorrast virna, kuni see on t\u00e4is. <\/p>\n<p><\/p>\n<p>Vaatame j\u00e4rgmine n\u00e4ide ja tegeleme selle samm-sammult \"teostamisega\". Samuti uurime, mis s\u00fcsteemis sellega toimub.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">console.log('Hi);\nsetTimeout(function cb1() {\n    console.log('cb1');\n}, 5000);\nconsole.log('Bye');<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/379423fca95fb28b2124be03dfd15739.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>1) Seni ei toimu midagi. Brauseri konsool on puhas, kutsumisvirn on t\u00fchi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/4a16bbc23bade54ae0b02d81d5f6a581.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>2) Siis lisatakse k\u00e4sk console.log('Hi') kutsumisekuhku.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a1845af23fd7dedebf94afc168f1f13f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>3) Ja see t\u00e4idetakse<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/57397b53386018b662f3a79a6d4d60fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>4) Seej\u00e4rel eemaldatakse console.log('Hi') kutsumisekuhust.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/7cb2b32be8807ecf39d2f38683ccd435.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>5) N\u00fc\u00fcd liikume k\u00e4su setTimeout(function cb1() {\u2026 }) juurde. See lisatakse kutsumissteigi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/99c0724994e3390d009577852b451beb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>6) K\u00e4sk setTimeout(function cb1() {\u2026 }) t\u00e4idetakse. Brauser loob taimeri, mis on osa Web API-st. See hakkab ajaloos tagasi lugema.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/99086cdeafd83c5fe72e92c4a9f9b738.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>7) K\u00e4sk setTimeout(function cb1() {\u2026 }) l\u00f5petab t\u00f6\u00f6 ja eemaldatakse kutsumissteigist.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/24ac12b1b6cfbff780ece9e9a7acd7c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>8) K\u00e4sk console.log('Bye') lisatakse kutsumisekuhku.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/6ccad0ad8eebf05e870a409766d38766.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>9) K\u00e4sk console.log('Bye') t\u00e4idetakse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/09e4e380eb873fb23bea550f3ffb21f7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>10) K\u00e4sk console.log('Bye') eemaldatakse kutsumisekuhust.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/357bfb372361310681ba7bb1860d90d7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>11) P\u00e4rast v\u00e4hemalt 5000 ms m\u00f6\u00f6dumist, taimer l\u00f5petab t\u00f6\u00f6 ja paneb kolmanda argumendi cb1 tagumise j\u00e4rjekorda.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/8170e8ff5d3d0c56c0091658370c25cc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>12) \u00dcrituste ts\u00fckkel v\u00f5tab funktsiooni cb1 tagumisest j\u00e4rjekorrast ja paneb selle kutsumissteigi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/d858a54e82bc32d84f854610db462bc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>13) Funktsioon cb1 t\u00e4idetakse ja lisab console.log('cb1') kutsumisekuhku.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/6ca8e016389904eec57035e64d57a157.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>14) K\u00e4sk console.log('cb1') t\u00e4idetakse.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/0caa645a90ac1fca5fb8a76569494d48.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>15) K\u00e4sk console.log('cb1') eemaldatakse kutsumisekuhust.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/aeb838fe8df3f6e3f8603a4207a6e193.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>16) Funktsioon cb1 eemaldatakse kutsumissteigist.<\/p>\n<p><\/p>\n<p>Vaadakem n\u00e4idet d\u00fcnaamikas:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/3836d9df513afee374f498720990e39f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Noh, oleme uurinud, kuidas JavaScriptis as\u00fcnkroonsus t\u00f6\u00f6tab. N\u00fc\u00fcd r\u00e4\u00e4gime l\u00fchidalt as\u00fcnkroonse koodi arengust.<\/p>\n<p><\/p>\n<h2 id=\"evolyuciya-asinhronnogo-koda\">As\u00fcnkroonse koodi areng.<\/h2>\n<p><\/p>\n<pre><code class=\"javascript\">a(function (resultsFromA) {\n    b(resultsFromA, function (resultsFromB) {\n        c(resultsFromB, function (resultsFromC) {\n            d(resultsFromC, function (resultsFromD) {\n                e(resultsFromD, function (resultsFromE) {\n                    f(resultsFromE, function (resultsFromF) {\n                        console.log(resultsFromF);\n                    })\n                })\n            })\n        })\n    })\n});<\/code><\/pre>\n<p><\/p>\n<p>As\u00fcnkroonne programmeerimine, nagu me seda JavaScripts tunneme, saab teostada ainult funktsioonidega. Need v\u00f5ivad olla edastatud nagu iga teine muutuja teistele funktsioonidele. Nii s\u00fcndisid tagasikutsed. Ja see on lahe, l\u00f5bus ja energiline, kuni see muutub kurvaks, igavaks ja masendavaks. Miks? Lihtsalt:<\/p>\n<p><\/p>\n<ul>\n<li>Koodi keerukuse suurenemisega muutub projekt kiiresti arusaamatuks mitmekordselt sisestatud plokkideks \u2014 \"callback hell\".<\/li>\n<li>Vea k\u00e4sitlemine v\u00f5ib kergesti ununeda.<\/li>\n<li>V\u00e4ljendeid ei saa tagastada return-iga.<\/li>\n<\/ul>\n<p><\/p>\n<p>Promises'i tulekuga paranes olukord veidi.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">new Promise(function(resolve, reject) {\n    setTimeout(() =&gt; resolve(1), 2000);\n\n}).then((result) =&gt; {\n    alert(result);\n    return result + 2;\n\n}).then((result) =&gt; {\n    throw new Error('FAIL HERE');\n    alert(result);\n    return result + 2;\n\n}).then((result) =&gt; {\n    alert(result);\n    return result + 2;\n\n}).catch((e) =&gt; {\n    console.log('error: ', e);\n});<\/code><\/pre>\n<p><\/p>\n<ul>\n<li>Tekkis lubade ahel, mis parandas koodi loetavust.<\/li>\n<li>Ilmus eraldi viga p\u00fc\u00fcdmise meetod.<\/li>\n<li>Ilmnes paralleelse t\u00e4itmise v\u00f5imalus Promise.all abil<\/li>\n<li>Sisemise as\u00fcnkroonsuse saame lahendada async\/await abil<\/li>\n<\/ul>\n<p><\/p>\n<p>Kuid lubadusel on oma piirangud. N\u00e4iteks lubadust ei saa t\u00fchistada ilma eriliste pingutusteta, ja mis veelgi olulisem - see t\u00f6\u00f6tab \u00fche v\u00e4\u00e4rtusega.<\/p>\n<p><\/p>\n<p>Noh, oleme sujuvalt j\u00f5udnud reaktiivse programmeerimise juurde. Kas olete v\u00e4sinud? \u00d5nneks on v\u00f5imalik minna tee keetmiseks, m\u00f5elda ja naasta lugema edasi. Aga mina j\u00e4tkan.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/48409ec625d57fec171214c1de332c85.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Reaktiivne programmeerimine<\/strong>\u2014 programmiskeem, mis keskendub andmevoogudele ja muutuste levitamisele. Vaatame l\u00e4hemalt, mis on andmevoog.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">\/\/ \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\nconst input = ducument.querySelector('input');\n\nconst eventsArray = [];\n\n\/\/ \u041f\u0443\u0448\u0438\u043c \u043a\u0430\u0436\u0434\u043e\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0432 \u043c\u0430\u0441\u0441\u0438\u0432 eventsArray\ninput.addEventListener('keyup',\n    event =&gt; eventsArray.push(event)\n);<\/code><\/pre>\n<p><\/p>\n<p>Kujutame ette, et meil on sisestusv\u00e4li. Loome massiivi ja salvestame iga input'i keyup s\u00fcndmuse meie massiivi. Samuti tahan m\u00e4rkida, et meie massiiv on j\u00e4rjestatud ajaliselt, st hilisemate s\u00fcndmuste indeks on suurem kui varasemate indeks. Selline massiiv esindab lihtsustatud andmevoogu, kuid see pole veel voog. Et seda massiivi saaks julgesti nimetada vooguks, peab see suutma mingil viisil teavitada tellijaid, et sinna on tulnud uusi andmeid. Seega j\u00f5udsime andmevoo m\u00e4\u00e4ratlemiseni.<\/p>\n<p><\/p>\n<h3 id=\"potok-dannyh\">Andmevoog<\/h3>\n<p><\/p>\n<pre><code class=\"javascript\">const { interval1 } = Rx;\nconst { take } = RxOperators;\n\ninterval(1000).pipe(\n    take(4)\n)<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/68ec447abafb6b8a323b429ed94f8252.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Voog<\/strong>\u2014 on ajaliselt j\u00e4rjestatud andmemassiiv, mis v\u00f5ib teavitada andmete muudatustest. Kujutage n\u00fc\u00fcd ette, kui mugav on kirjutada koodi, kus \u00fche tegevuse jaoks tuleb kutsuda mitu s\u00fcndmust erinevates koodil\u00f5ikudes. Me lihtsalt tellime voogu ja see teavitab meid automaatselt, kui muudatused toimuvad. Ja seda suudab RxJs teek.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/dcb1cfca8b4d8a887b63c302a7d6c06a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>RxJS <\/strong> \u2014 on teek as\u00fcnkroonsete ja s\u00fcndmustel p\u00f5hinevate programmide jaoks, kasutades j\u00e4lgitavaid j\u00e4rjestusi. Teek pakub p\u00f5hity\u00fcpi <em>Observable<\/em>, mitu abistavat t\u00fc\u00fcpi (<em>Observer, Schedulers, Subjects<\/em>) ja s\u00fcndmuste t\u00f6\u00f6tlemise operaatorid nagu kogumite puhul (<em>map, filter, reduce, every<\/em> ja sarnased JavaScripti massiivist).<\/p>\n<p><\/p>\n<p>Vaatame p\u00f5hikontseptsioone, mis selles teegis on.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable on esimene p\u00f5hiklass, millega me tutvume. See klass sisaldab RxJs rakenduse p\u00f5hij\u00f5udu. See on seotud j\u00e4lgitava vooguga, millele saab registreeruda meetodi subscribe kaudu.<\/p>\n<p><\/p>\n<p>Observable'is on rakendatud abimehhanism v\u00e4rskenduste loomiseks, nii \u00f6eldakse <em>Observer<\/em>. K\u00f5iki Observer'i v\u00e4\u00e4rtusi,tootjat nimetatakse <em>Producer<\/em>. See v\u00f5ib olla massiiv, iteratsioon, web soket, mingi s\u00fcndmus jne. Seega v\u00f5ib \u00f6elda, et observable on vahendaja Producer'i ja Observer'i vahel. <\/p>\n<p><\/p>\n<p>Observable t\u00f6\u00f6tleb kolme t\u00fc\u00fcpi \u00fcritusi Observer'ile:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 uued andmed<\/li>\n<li>error \u2013 viga, kui jada l\u00f5ppes erandi t\u00f5ttu. see s\u00fcndmus eeldab ka jada l\u00f5petamist.<\/li>\n<li>complete \u2014 signaal jada l\u00f5petamiseks. See t\u00e4hendab, et uusi andmeid enam ei tule.<\/li>\n<\/ul>\n<p><\/p>\n<p>Vaadakem demo:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c5bcd2af0f18b6de3ab0dbc20db595d1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Alustame v\u00e4\u00e4rtuste 1, 2, 3 t\u00f6\u00f6tlemisest, ja p\u00e4rast 1 sekundit saame 4 ning l\u00f5petame meie voolu.<\/p>\n<p>\n<b class=\"spoiler_title\">M\u00f5tisklen<\/b><\/p>\n<p>Ja siis m\u00f5istsin, et r\u00e4\u00e4kimine oli huvitavam kui sellest kirjutamine. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Subscription<\/h3>\n<p><\/p>\n<p>Kui me registreerume voogule, loome uue klassi <strong>subscription<\/strong>, mis v\u00f5imaldab meil t\u00fchistada tellimuse meetodi <em>unsubscribe<\/em>kaudu. Samuti saame tellimusi r\u00fchmitada meetodi kaudu <em>add<\/em>. Ja on m\u00f5istetav, et saame vooge eraldada meetodi abil <em>eemalda<\/em>. Meetodid add ja remove v\u00f5tavad sisse teise tellimuse. Tahaksin m\u00e4rkida, et kui me t\u00fchistame tellimuse, siis t\u00fchistame me ka k\u00f5ik alamtellimused just nagu oleksime neile k\u00e4skinud meetodit unsubscribe. J\u00e4tkame.<\/p>\n<p><\/p>\n<h3 id=\"vidy-potokov\">Vood t\u00fc\u00fcbid<\/h3>\n<p><\/p>\n<table>\n<thead>\n<tr>\n<th>HOT<\/th>\n<th>COLD<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Producer luuakse observable'ist v\u00e4ljaspool<\/td>\n<td>Producer luuakse observable'i sees<\/td>\n<\/tr>\n<tr>\n<td>Andmed edastatakse observable'i loomise hetkel<\/td>\n<td>Andmed edastatakse tellimise hetkel<\/td>\n<\/tr>\n<tr>\n<td>Tuleb lisaloogika t\u00fchistamiseks<\/td>\n<td>Voo l\u00f5petab iseennast<\/td>\n<\/tr>\n<tr>\n<td>Kasutab \u00fchte-korra-mitmele seondumist<\/td>\n<td>Kasutab \u00fche-korra-\u00fchele seondumist<\/td>\n<\/tr>\n<tr>\n<td>K\u00f5ik tellimused omavad \u00fchte v\u00e4\u00e4rtust<\/td>\n<td>Tellimused on s\u00f5ltumatud<\/td>\n<\/tr>\n<tr>\n<td>Andmed v\u00f5ivad kaduda, kui tellimust ei ole<\/td>\n<td>Taask\u00e4ideldakse k\u00f5iki voolu v\u00e4\u00e4rtusi uus tellimus<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Kui tuua analoogia, siis kujutaksin kuuma voolu nagu filmi kinos. Millal sa kohale j\u00f5udsid, sellest hetkest alates hakad vaatama. K\u00fclma voolu v\u00f5iksin v\u00f5rrelda tehnilise toe k\u00f5nega. Iga helistaja kuulab vastusautomaatide salvestust algusest l\u00f5puni, kuid saad telefonik\u00f5ne katkestada meetodiga unsubscribe.<\/p>\n<p><\/p>\n<p>Tahaksin m\u00e4rkida, et eksisteerivad ka nn soojad vood (seda m\u00e4\u00e4ratlust kohtasin \u00e4\u00e4rmiselt harva ja ainult v\u00e4lisriikide kogukondades) \u2014 see on voog, mis transformeerub k\u00fclmast voost kuumaks. K\u00fcsitav on, kus seda kasutada)) Toon n\u00e4ite praktikast.<\/p>\n<p><\/p>\n<p>T\u00f6\u00f6tan angulaariga. See kasutab aktiivselt rxjs-i. Serverist andmete saamiseks ootan k\u00fclma voogu ja kasutan seda \u0161abloonis koos asyncPipe'iga. Kui kasutan seda pipa mitu korda, siis naastes k\u00fclma voolu m\u00e4\u00e4ratlemise juurde, taotleb iga pipa andmeid serverist, mis on pehmelt \u00f6eldes kummaline. Kui aga muudan k\u00fclma voogu soojaks, siis toimub p\u00e4ring \u00fcks kord.<\/p>\n<p><\/p>\n<p>\u00dcldiselt on voogude t\u00fc\u00fcpide m\u00f5istmine algajatele piisavalt keeruline, kuid oluline. <\/p>\n<p><\/p>\n<h3 id=\"operators\">Operaatorid<\/h3>\n<p><\/p>\n<pre><code class=\"javascript\">return this.http.get(`${environment.apiUrl}\/${this.apiUrl}\/trade_companies`)\n    .pipe(\n        tap(({ data }: TradeCompanyList) =&gt; this.companies$$.next(cloneDeep(data))),\n        map(({ data }: TradeCompanyList) =&gt; data)\n    );<\/code><\/pre>\n<p><\/p>\n<p>Operaatorid pakuvad meile laiendatud v\u00f5imalusi voogudega t\u00f6\u00f6tamiseks. Need aitavad kontrollida Observable'is toimuvaid s\u00fcndmusi. K\u00e4sitleme m\u00f5nda k\u00f5ige populaarsemat, kuid operaatoritega saab l\u00e4hemalt tutvuda kasuliku info lingil.<\/p>\n<p><\/p>\n<p><strong>Operaatorid \u2014 of<\/strong><\/p>\n<p><\/p>\n<p>Alustame abistava operaatori of'iga. See loob Observable'i lihtsast v\u00e4\u00e4rtusest.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/68f382447e306392b025867a9a1e88e7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operaatorid \u2014 filter<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/24ac65fdb5ccc7f6301b3dfe49f1e804.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Filteroperaator filter, nagu nimi \u00fctleb, filtreerib voolu signaali. Kui operaator tagastab t\u00f5e, siis lastakse see edasi.<\/p>\n<p><\/p>\n<p><strong>Operaatorid \u2014 take<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/b3e7a2a2e03038d6fc250247ff4496a2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>take \u2014 V\u00f5tab vastu emitatsioonide arvu, p\u00e4rast mida l\u00f5petab voo.<\/p>\n<p><\/p>\n<p><strong>Operaatorid \u2014 debounceTime<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/add686e546a0b6169c38fb3b457da928.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>debounceTime \u2014 viskab k\u00f5rvale emitatsioonid, mis satuvad m\u00e4\u00e4ratud aja vahemikku v\u00e4ljundite vahel \u2014 p\u00e4rast ajavahemiku m\u00f6\u00f6dumist emititakse viimane v\u00e4\u00e4rtus.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { Observable } = Rx;\nconst { debounceTime, take } = RxOperators;\n\nObservable.create((observer) =&gt; {\n  let i = 1;\n  observer.next(i++);\n  \/\/ Emitime v\u00e4\u00e4rtuse iga 1000 ms j\u00e4rel\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n\n  \/\/ Emitime v\u00e4\u00e4rtuse iga 1500 ms j\u00e4rel\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1500);\n}).pipe(\n  debounceTime(700),  \/\/ Ootame 700 ms v\u00e4\u00e4rtuse enne t\u00f6\u00f6tlemist\n  take(3)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/dbb690d6fea6c43c1f0a2bdabea57934.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operaatorid \u2014 takeWhile<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/120d9fe6ddf5a60ddffc8742989b27ff.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Emitib v\u00e4\u00e4rtusi, kuni takeWhile ei tagasta false, p\u00e4rast mida loobub voost.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { Observable } = Rx;\nconst { debounceTime, takeWhile } = RxOperators;\n\nObservable.create((observer) =&gt; {\n  let i = 1;\n  observer.next(i++);\n  \/\/ Emit value every 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n}).pipe(\n  takeWhile(producer =&gt; producer &lt; 5)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/d2910d1bf9fab228acc9241fdbad3d4a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operators \u2014 combineLatest<\/strong><\/p>\n<p><\/p>\n<p>Kombineeritud operaator combineLatest sarnaneb promise.all-iga. See \u00fchendab mitmed vood \u00fchte. P\u00e4rast seda, kui iga voog on teinud v\u00e4hemalt \u00fche emit'i, saame viimasest v\u00e4\u00e4rtused iga\u00fche kohta massiivina. Edasi, p\u00e4rast mida tahes \u00fchte emit'i \u00fchendatud voogudest, annab see uusi v\u00e4\u00e4rtusi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c39bc0a8a736ed30ad147055110bbf55.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { combineLatest, Observable } = Rx;\nconst { take } = RxOperators;\n\nconst observer_1 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 1000ms\n  setInterval(() =&gt; {\n    observer.next('a: ' + i++);\n  }, 1000);\n});\n\nconst observer_2 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 750ms\n  setInterval(() =&gt; {\n    observer.next('b: ' + i++);\n  }, 750);\n});\n\ncombineLatest(observer_1, observer_2).pipe(take(5));<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/7fc35461f446987ef81302ff7c2ed5a8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operators \u2014 zip<\/strong><\/p>\n<p><\/p>\n<p>Zip ootab v\u00e4\u00e4rtust igast voost ja moodustab massiivi nende v\u00e4\u00e4rtuste p\u00f5hjal. Kui v\u00e4\u00e4rtus ei tule \u00fcheltki voost, siis gruppi ei moodustata.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/0be5ee0d2ec56bd2bc245b15d43d4cc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { zip, Observable } = Rx;\nconst { take } = RxOperators;\n\nconst observer_1 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 1000ms\n  setInterval(() =&gt; {\n    observer.next('a: ' + i++);\n  }, 1000);\n});\n\nconst observer_2 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 750\n  setInterval(() =&gt; {\n    observer.next('b: ' + i++);\n  }, 750);\n});\n\nconst observer_3 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 500\n  setInterval(() =&gt; {\n    observer.next('c: ' + i++);\n  }, 500);\n});\n\nzip(observer_1, observer_2, observer_3).pipe(take(5));<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/e2606bf8ea5f8a660699ebe896a27d80.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operators \u2014 forkJoin<\/strong><\/p>\n<p><\/p>\n<p>forkJoin \u00fchendab ka vood, kuid emit'ib v\u00e4\u00e4rtuse ainult siis, kui k\u00f5ik vood on l\u00f5petatud (complete).<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/6c430d7eeafbc8a7c1c228ddfe0e44b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { forkJoin, Observable } = Rx;\nconst { take } = RxOperators;\n\nconst observer_1 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 1000ms\n  setInterval(() =&gt; {\n    observer.next('a: ' + i++);\n  }, 1000);\n}).pipe(take(3));\n\nconst observer_2 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 750\n  setInterval(() =&gt; {\n    observer.next('b: ' + i++);\n  }, 750);\n}).pipe(take(5));\n\nconst observer_3 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 500\n  setInterval(() =&gt; {\n    observer.next('c: ' + i++);\n  }, 500);\n}).pipe(take(4));\n\nforkJoin(observer_1, observer_2, observer_3);<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/df110efc7ece46fc1d8da2d7693f75bb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operators \u2014 map<\/strong><\/p>\n<p><\/p>\n<p>Muutmisoperaator map muudab emit'i v\u00e4\u00e4rtuse uueks. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/2196ff9f82dd7aaeb00ab76475176d32.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { Observable } = Rx;\nconst { take, map } = RxOperators;\n\nObservable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++);\n  }, 1000);\n}).pipe(\n  map(x =&gt; x * 10),\n  take(3)\n);\n<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/4e4ff3e2eb4acf69f16559c711a2e666.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operators \u2013 share, tap<\/strong><\/p>\n<p><\/p>\n<p>K\u00e4sk tap \u2014 v\u00f5imaldab teha k\u00f5rvalm\u00f5jusid, st teatud tegevusi, mis ei m\u00f5juta j\u00e4rjekorda.<\/p>\n<p><\/p>\n<p>Abiooperator share suudab k\u00fclma voolu muuta kuumaks. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"As\u00fcnkroonne programmeerimine JavaScriptis. (Tagasiside, Lubadus, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c46e96420ed78d197ceef829ff74c82d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Oleme operaatoritega l\u00f5petanud. Liigume subjektide juurde.<\/p>\n<p>\n<b class=\"spoiler_title\">M\u00f5tisklen<\/b><\/p>\n<p>Ja siis l\u00e4ksin ma teed jooma. Need n\u00e4ited v\u00e4sitasid mind \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">Subjektide perekond<\/h2>\n<p><\/p>\n<p>Subjektide perekond on ilmekas n\u00e4ide kuumadest voogudest. Need klassid on teatud h\u00fcbriid, mis toimivad samal ajal nii observable kui observerina. Kuna subjekt on kuum voog, tuleb sellelt maha registreerida. Peamised meetodid on:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 andmete edastamine voogu<\/li>\n<li>error \u2013 voogu l\u00f5petamine ja viga<\/li>\n<li>complete \u2013 voogu l\u00f5petamine<\/li>\n<li>subscribe \u2013 voogu registreerimine<\/li>\n<li>unsubscribe \u2013 voogust maha registreerimine<\/li>\n<li>asObservable \u2013 muudame vaatlejaks<\/li>\n<li>toPromise \u2013 muudab lubaduseks<\/li>\n<\/ul>\n<p><\/p>\n<p>Erakordselt on 4-5 t\u00fc\u00fcpi subjekte. <\/p>\n<p>\n<b class=\"spoiler_title\">M\u00f5tisklen<\/b><\/p>\n<p>Streamil r\u00e4\u00e4kisin 4, aga selgus, et nad on \u00fche veel lisanud. Nagu \u00f6eldakse, elad ja \u00f5pid.<\/p>\n<p><\/p>\n<p>Lihtne Subject <code>new Subject()<\/code>\u2013 k\u00f5ige lihtsam t\u00fc\u00fcp subjekte. Loob ilma parameetriteta. Edastab v\u00e4\u00e4rtusi, mis saabuvad vaid p\u00e4rast registreerimist.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject(defaultData&lt;T&gt;)<\/code> \u2013 minu arvates k\u00f5ige levinum t\u00fc\u00fcp subjekte. V\u00f5tab sisendiks vaikev\u00e4\u00e4rtuse. Hoidub alati viimase edastuse andmetest, mille ta edastab registreerimise ajal. Sellel klassil on samuti kasulik meetod value, mis tagastab voolu praeguse v\u00e4\u00e4rtuse.<\/p>\n<p><\/p>\n<p>ReplaySubject <code>new ReplaySubject(bufferSize?: number, windowTime?: number)<\/code> \u2013 V\u00f5tab sisendiks valikuliselt esmase argumendina v\u00e4\u00e4rtuste puhvri suuruse, mille ta enda sisse salvestab, ja teise argumentina aja, mille jooksul on meil muudatused vajalikud.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> \u2013 registreerimisel ei toimu midagi, ja v\u00e4\u00e4rtus naastes ainult siis, kui voog on l\u00f5petatud. Tagastatakse ainult voolu viimane v\u00e4\u00e4rtus.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig&lt;T&gt; | Observable&lt;T&gt;, destination?: Observer&lt;T&gt;)<\/code> \u2013 Dokumentatsioon selle kohta ei r\u00e4\u00e4gi ja n\u00e4en seda esmakordselt. Kes teab, mida see teeb, kirjutage, t\u00e4iendame.<\/p>\n<p><\/p>\n<p>Ohh. Noh, oleme n\u00fc\u00fcd l\u00e4binud k\u00f5ik, mida tahtsin t\u00e4na jagada. Loodan, et see teave oli kasulik. Iseseisvalt saab kirjanduse nimekirjaga tutvuda kasulike info sektsioonist.<\/p>\n<p><\/p>\n<h2 id=\"poleznaya-informaciya\">Kasulik teave<\/h2>\n<p><\/p>\n<ul>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/vk.com\/frontend_practice?w=wall-182297870_931\">https:\/\/vk.com\/frontend_practice?w=wall-182297870_931<\/a><\/noindex> \u2013 link streamile<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/337042\/\">https:\/\/habr.com\/ru\/company\/ruvds\/blog\/337042\/<\/a><\/noindex> \u2013 Kuidas JS t\u00f6\u00f6tab: \u00fclevaade mootori, k\u00e4itamise mehhanismide, v\u00e4ljakutsumise virna kohta<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/340508\/\">https:\/\/habr.com\/ru\/company\/ruvds\/blog\/340508<\/a><\/noindex> \u2014 Kuidas t\u00f6\u00f6tab JS: s\u00fcndmuste ts\u00fckkel, as\u00fcnkroonsus ja viis viisi koodi parendamiseks async \/ await abil<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"http:\/\/vanilla-js.blogspot.com\/2014\/09\/event-loop-javasript.html\">http:\/\/vanilla-js.blogspot.com\/2014\/09\/event-loop-javasript.html<\/a><\/noindex> \u2014 Kuidas t\u00f6\u00f6tab Event Loop JavaScriptis<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/tproger.ru\/translations\/asynchronous-javascript\/\">https:\/\/tproger.ru\/translations\/asynchronous-javascript\/<\/a><\/noindex> \u2014 As\u00fcnkroonse JavaScripti evolutsioon<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/341880\/\">https:\/\/habr.com\/ru\/company\/ruvds\/blog\/341880\/<\/a><\/noindex> \u2014 Mis on RxJS ja miks on sellest kasulik teada<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/ngx\/practical-use-rxjs-81aaab57045c\">https:\/\/medium.com\/ngx\/practical-use-rxjs-81aaab57045c<\/a><\/noindex> \u2014 Praktiline rakendamine RxJS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/coursetro.com\/posts\/code\/148\/RxJS-Observables-Tutorial---Creating-&amp;-Subscribing-to-Observables\">https:\/\/coursetro.com\/posts\/code\/148\/RxJS-Observables-Tutorial&#8212;Creating-&amp;-Subscribing-to-Observables<\/a><\/noindex> \u2014 RxJS Observablesi \u00f5petus \u2014 loomine ja tellimine observablest<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/slides.com\/zenabsaleem\/rxjs-hot-cold-observables#\/\">https:\/\/slides.com\/zenabsaleem\/rxjs-hot-cold-observables#\/<\/a><\/noindex> \u2014 RXJS: kuumad ja k\u00fclmad observablid<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FiPgB\">https:\/\/clck.ru\/FiPgB<\/a><\/noindex> \u2014 Klassid, funktsioonid observablite loomiseks. Operiatorid.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.learnrxjs.io\/operators\/\">https:\/\/www.learnrxjs.io\/operators\/<\/a><\/noindex> \u2014 RxJS operaatorid n\u00e4ite kaudu<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/rxjs.dev\/api\">https:\/\/rxjs.dev\/api<\/a><\/noindex> \u2014 API loetelu<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FkS8Y\">https:\/\/clck.ru\/FkS8Y<\/a><\/noindex> \u2014 Subjectide ja ajakava t\u00fc\u00fcbid RxJS-is<\/li>\n<\/ul>\n<p>Allikas: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/462355\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u041e\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u043a\u0438\u0439 \u0421\u0435\u0440\u0433\u0435\u0439. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0432\u0435\u043b \u0441\u0442\u0440\u0438\u043c \u043f\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0432 JavaScript. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u043a\u043e\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b. \u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0432\u043e\u0434\u043d\u0443\u044e. \u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0439: \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0441\u0442\u0435\u043a \u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u044c? \u0421\u0442\u0435\u043a \u2014 \u044d\u0442\u043e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f, \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0439 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27545,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-36774","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u041e\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u043a\u0438\u0439 \u0421\u0435\u0440\u0433\u0435\u0439. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0432\u0435\u043b \u0441\u0442\u0440\u0438\u043c \u043f\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0432 JavaScript. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u043a\u043e\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/et\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\n\t\t<meta property=\"og:locale\" content=\"et_EE\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 JavaScript. ( Callback, Promise, RxJs ) | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u041e\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u043a\u0438\u0439 \u0421\u0435\u0440\u0433\u0435\u0439. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0432\u0435\u043b \u0441\u0442\u0440\u0438\u043c \u043f\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0432 JavaScript. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u043a\u043e\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/et\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:13:44+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:13:44+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47As\u00fcnkroonne programmeerimine JavaScriptis. (Callback, Promise, RxJs) | ProHoster","description":"Tere k\u00f5igile. Siin on Omelnitski Sergei. Hiljuti viisin l\u00e4bi voogedastuse reaktiivprogrammeerimise kohta, kus r\u00e4\u00e4kisin as\u00fcnkroonsusest JavaScriptis. T\u00e4na tahaksin selle materjali kokku v\u00f5tta.","canonical_url":"https:\/\/prohoster.info\/et\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"et_EE","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 JavaScript. ( Callback, Promise, RxJs ) | ProHoster","og:description":"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u041e\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u043a\u0438\u0439 \u0421\u0435\u0440\u0433\u0435\u0439. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0432\u0435\u043b \u0441\u0442\u0440\u0438\u043c \u043f\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0432 JavaScript. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u043a\u043e\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.","og:url":"https:\/\/prohoster.info\/et\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:13:44+00:00","article:modified_time":"2019-10-31T19:13:44+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36774","title":null,"description":null,"keywords":null,"keyphrases":{"focus":[],"additional":[]},"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:48:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:39:22","updated":"2026-08-11 12:50:32","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/36774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/comments?post=36774"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/posts\/36774\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media\/27545"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/media?parent=36774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/categories?post=36774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/et\/wp-json\/wp\/v2\/tags?post=36774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}