{"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\/hr\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","title":{"rendered":"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Pozdrav svima. Ovde je Sergej Omelnitzki. Nedavno sam imao stream o reaktivnom programiranju, gde sam pri\u010dao o asinhronosti u JavaScriptu. Danas bih \u017eeleo da sa\u017emem ovaj materijal. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/11acf6af8328d3deb6f0ce48e813efb7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ali pre nego \u0161to zapo\u010dnemo glavni materijal, potrebno je da uradimo uvod. Dakle, hajde da po\u010dnemo s definicijama: \u0161ta je stek i red?<br \/>\n<strong>Stek <\/strong>je kolekcija \u010diji se elementi uzimaju po principu \u201eposlednji do\u0161ao, prvi oti\u0161ao\u201c LIFO<br \/>\n<strong>Red <\/strong>je kolekcija \u010diji se elementi uzimaju po principu \u201eprvi do\u0161ao, prvi oti\u0161ao\u201c FIFO<\/p>\n<p><\/p>\n<p>U redu, nastavljamo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/a7d64d1c74f37b463869dd57b96c9d0e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>JavaScript je jezgro za programiranje sa jednim tokom. To zna\u010di da postoji samo jedan tok izvr\u0161avanja i jedan stek, u koji se funkcije stavljaju u red za izvr\u0161avanje. Samim tim, u jednom trenutku JavaScript mo\u017ee izvr\u0161iti samo jednu operaciju, dok ostale operacije \u010dekaju svoj red u steku, dok ne budu pozvane. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Stek poziva<\/strong> je struktura podataka koja, pojednostavljeno re\u010deno, bele\u017ei informacije o mestu u programu gde se nalazimo. Ako ulazimo u funkciju, sme\u0161tamo njen zapis na vrh steka. Kada se vra\u0107amo iz funkcije, uzimamo najgornji element iz steka i vra\u0107amo se na mesto odakle smo pozvali tu funkciju. To je sve \u0161to stek radi. A sada izuzetno zanimljivo pitanje. Kako onda radi asinhronost u JavaScriptu?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/a29fd1dd3de06fb203c7dd14bda30548.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>U stvari, pored steka, u browserima postoji poseban red za rad sa takozvanim WebAPI. Funkcije iz ovog reda bi\u0107e izvr\u0161ene redom tek nakon \u0161to se stek potpuno isprazni. Tek tada se prebacuju iz reda u stek za izvr\u0161avanje. Ako u steku trenutno postoji barem jedan element, one ne mogu do\u0107i u stek. Zbog toga, pozivi funkcija putem timeouta \u010desto nisu ta\u010dni u vremenu, jer funkcija ne mo\u017ee u\u0107i iz reda u stek dok je on pun. <\/p>\n<p><\/p>\n<p>Razmotri\u0107emo slede\u0107i primer i posvetiti se njegovom korak-po-korak \u201eizvr\u0161enju\u201c. Tako\u0111e, razmotri\u0107emo \u0161ta se u tom trenutku de\u0161ava u sistemu.<\/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=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/379423fca95fb28b2124be03dfd15739.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>1) Dok se ni\u0161ta ne de\u0161ava. Konzola browsera je prazna, stek poziva je prazan.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/4a16bbc23bade54ae0b02d81d5f6a581.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>2) Zatim se naredba console.log('Hi') dodaje u stek poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/a1845af23fd7dedebf94afc168f1f13f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>3) I ona se izvr\u0161ava<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/57397b53386018b662f3a79a6d4d60fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>4) Potom se console.log('Hi') uklanja iz steka poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/7cb2b32be8807ecf39d2f38683ccd435.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>5) Sada prelazimo na naredbu setTimeout(function cb1() {\u2026 }). Ona se dodaje u stog poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/99c0724994e3390d009577852b451beb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>6) Naredba setTimeout(function cb1() {\u2026 }) se izvr\u0161ava. Preglednik kreira tajmer koji je deo Web API-ja. On \u0107e izvr\u0161iti odbrojavanje.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/99086cdeafd83c5fe72e92c4a9f9b738.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>7) Naredba setTimeout(function cb1() {\u2026 }) je zavr\u0161ila sa radom i uklanja se iz stoga poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/24ac12b1b6cfbff780ece9e9a7acd7c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>8) Naredba console.log('Bye') dodaje se u stek poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/6ccad0ad8eebf05e870a409766d38766.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>9) Naredba console.log('Bye') se izvr\u0161ava.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/09e4e380eb873fb23bea550f3ffb21f7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>10) Naredba console.log('Bye') uklanja se iz steka poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/357bfb372361310681ba7bb1860d90d7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>11) Nakon \u0161to pro\u0111e najmanje 5000 ms, tajmer zavr\u0161ava sa radom i stavlja povratni poziv cb1 u red povratnih poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/8170e8ff5d3d0c56c0091658370c25cc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>12) Ciklus doga\u0111aja uzima funkciju cb1 iz reda povratnih poziva i stavlja je u stog poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/d858a54e82bc32d84f854610db462bc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>13) Funkcija cb1 se izvr\u0161ava i dodaje console.log('cb1') u stek poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/6ca8e016389904eec57035e64d57a157.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>14) Naredba console.log('cb1') se izvr\u0161ava.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/0caa645a90ac1fca5fb8a76569494d48.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>15) Naredba console.log('cb1') uklanja se iz steka poziva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/aeb838fe8df3f6e3f8603a4207a6e193.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>16) Funkcija cb1 se uklanja iz stoga poziva.<\/p>\n<p><\/p>\n<p>Pogledajmo primer u dinamici:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/3836d9df513afee374f498720990e39f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Evo kako smo obradili asinkronost u JavaScript-u. Sada hajde da ukratko razgovaramo o evoluciji asinkronog koda.<\/p>\n<p><\/p>\n<h2 id=\"evolyuciya-asinhronnogo-koda\">Evolucija asinkronog koda.<\/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>Asinkrono programiranje, kakvo ga poznajemo u JavaScript-u, mo\u017ee se realizovati samo funkcijama. One se mogu preneti kao bilo koja druga promenljiva drugim funkcijama. Tako su ro\u0111eni povratni pozivi. I to je zabavno i veselo, sve dok se ne pretvori u tugu i jad. Za\u0161to? Zato \u0161to:<\/p>\n<p><\/p>\n<ul>\n<li>Sa pove\u0107anjem slo\u017eenosti koda, projekat brzo postaje te\u0161ko razumljiv sa vi\u0161e nivoa ugnje\u017edenih blokova \u2014 \u201eozbiljna tjeskoba sa povratnim pozivima\u201c.<\/li>\n<li>Obrada gre\u0161aka se lako mo\u017ee propustiti.<\/li>\n<li>Ne mo\u017eete vra\u0107ati izraze sa return.<\/li>\n<\/ul>\n<p><\/p>\n<p>Sa pojavom Promise situacija se malo pobolj\u0161ala.<\/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('NEUSPJEH OVDJE');\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('gre\u0161ka: ', e);\n});<\/code><\/pre>\n<p><\/p>\n<ul>\n<li>Pojavili su se lanci proma, \u0161to je pobolj\u0161alo \u010ditljivost koda<\/li>\n<li>Pojavila se posebna metoda za hvatanje gre\u0161aka<\/li>\n<li>Pojavila se mogu\u0107nost paralelnog izvr\u0161avanja pomo\u0107u Promise.all<\/li>\n<li>Ugnije\u017e\u0111enu asinkronost mo\u017eemo rije\u0161iti pomo\u0107u async\/await<\/li>\n<\/ul>\n<p><\/p>\n<p>Ali promisi imaju svoja ograni\u010denja. Na primjer, niti jedan promisor se ne mo\u017ee otkazati bez dodatnog truda, a \u0161to je jo\u0161 va\u017enije \u2014 radi sa jednom vrijedno\u0161\u0107u.<\/p>\n<p><\/p>\n<p>Pa, polako smo do\u0161li do reaktivnog programiranja. Umorni ste? Pa dobro, mo\u017eete skuhati \u010daj, razmisliti i vratiti se \u010ditanju. A ja \u0107u nastaviti.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/48409ec625d57fec171214c1de332c85.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Reaktivno programiranje<\/strong>\u2014 paradigma programiranja usmjerena na tokove podataka i distribuciju promjena. Pogledajmo detaljnije \u0161to je to tok podataka.<\/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>Zamislimo da imamo polje za unos. Kreiramo niz i na svaki keyup doga\u0111aj unosa \u0107emo spremiti doga\u0111aj u na\u0161em nizu. Tako\u0111er, va\u017eno je napomenuti da je na\u0161 niz sortirano prema vremenu \u2014 tj. indeks kasnijih doga\u0111aja je ve\u0107i od indeksa ranijih. Takav niz predstavlja pojednostavljeni model toka podataka, ali to jo\u0161 nije tok. Da bismo ovaj niz mogli slobodno nazvati tokom, mora na neki na\u010din obavijestiti pretplatnike da su stigli novi podaci. Na taj na\u010din smo do\u0161li do definicije toka.<\/p>\n<p><\/p>\n<h3 id=\"potok-dannyh\">Tok podataka<\/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=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/68ec447abafb6b8a323b429ed94f8252.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Tok<\/strong>\u2014 to je niz podataka, sortiranih prema vremenu, koji mo\u017ee obavijestiti da su podaci promijenjeni. A sada zamislite koliko je zgodno pisati kod u kojem \u0107e na jedan doga\u0111aj biti potrebno pozvati nekoliko doga\u0111aja na razli\u010ditim mjestima u kodu. Jednostavno se pretplatimo na tok i on \u0107e nas sam obavijestiti kada do\u0111e do promjena. To mo\u017ee u\u010diniti biblioteka RxJs.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, 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 to je biblioteka za rad s asinkronim i doga\u0111ajima temeljenim programima koriste\u0107i promatra\u010dke sekvence. Biblioteka pru\u017ea osnovni tip <em>Observable<\/em>, nekoliko pomo\u0107nih tipova (<em>Observer, Schedulers, Subjects<\/em>) i operatore za rad s doga\u0111ajima kao kolekcijama (<em>map, filter, reduce, every<\/em> i sli\u010dne iz JavaScript Array).<\/p>\n<p><\/p>\n<p>Pogledajmo osnovne pojmove ove biblioteke.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable \u2014 prvi osnovni tip koji \u0107emo razmotriti. Ova klasa sadr\u017ei glavni deo implementacije RxJs. Ona je povezana s posmatranim tokom kojem se mo\u017ee pristupiti putem metode subscribe.<\/p>\n<p><\/p>\n<p>U Observable se implementira pomo\u0107ni mehanizam za kreiranje a\u017euriranja, takozvani <em>Observer<\/em>. Izvor vrednosti za Observer se naziva <em>Producer<\/em>. To mo\u017ee biti niz, iterator, web soket, neki doga\u0111aj itd. Tako da mo\u017eemo re\u0107i da je observable posrednik izme\u0111u Producer i Observer. <\/p>\n<p><\/p>\n<p>Observable obra\u0111uje tri vrste doga\u0111aja Observer:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 novi podaci<\/li>\n<li>error \u2013 gre\u0161ku, ako se sekvenca zavr\u0161ila zbog izuzetne situacije. Ovaj doga\u0111aj tako\u0111e podrazumeva zavr\u0161etak sekvence.<\/li>\n<li>complete \u2014 signal o zavr\u0161etku sekvence. To zna\u010di da novih podataka vi\u0161e ne\u0107e biti.<\/li>\n<\/ul>\n<p><\/p>\n<p>Pogledajmo demo:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/c5bcd2af0f18b6de3ab0dbc20db595d1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na po\u010detku \u0107emo obraditi vrednosti 1, 2, 3, a nakon 1 sekunde dobijamo 4 i zavr\u0161avamo na\u0161 tok.<\/p>\n<p>\n<b class=\"spoiler_title\">Misli na glas<\/b><\/p>\n<p>I tu sam shvatio da je zanimljivije pri\u010dati nego pisati o tome. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Subscription<\/h3>\n<p><\/p>\n<p>Kada se pretplatimo na tok, kreiramo novu klasu <strong>subscription<\/strong>, koja nam omogu\u0107ava da otka\u017eemo pretplatu putem metode <em>unsubscribe<\/em>. Tako\u0111e mo\u017eemo grupisati pretplate pomo\u0107u metode <em>add<\/em>. Pa je logi\u010dno da mo\u017eemo odgrupisati tokove pomo\u0107u <em>remove<\/em>. Metode add i remove prihvataju drugu pretplatu kao argument. Voleo bih naglasiti da kada se odjavimo, odjavljujemo se od svih podpretplata kao da smo i njima pozvali metodu unsubscribe. Idemo dalje.<\/p>\n<p><\/p>\n<h3 id=\"vidy-potokov\">Vrste tokova<\/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 se kreira spolja observable<\/td>\n<td>Producer se kreira unutar observable<\/td>\n<\/tr>\n<tr>\n<td>Podaci se prenose prilikom kreiranja observable<\/td>\n<td>Podaci se dostavljaju prilikom pretplate<\/td>\n<\/tr>\n<tr>\n<td>Potrebna je dodatna logika za odjavu<\/td>\n<td>Tok se zavr\u0161ava samostalno<\/td>\n<\/tr>\n<tr>\n<td>Koristi vezu jedan-na-mnoge<\/td>\n<td>Koristi vezu jedan-na-jedan<\/td>\n<\/tr>\n<tr>\n<td>Sve pretplate imaju jedinstvenu vrednost<\/td>\n<td>Pretplate su nezavisne<\/td>\n<\/tr>\n<tr>\n<td>Podaci se mogu izgubiti ako nema pretplate<\/td>\n<td>Ponovno izdaje sve vrednosti toka za novu pretplatu<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Ako bismo povukli analogiju, predstavi\u0107u vru\u0107i tok kao film u bioskopu. U kom trenutku si do\u0161ao, od tog trenutka i po\u010dinje\u0161 gledanje. Hladni tok bih uporedio sa pozivom u tehni\u010dku podr\u0161ku. Svaki pozivatelj slu\u0161a snimak automatskog odgovara od po\u010detka do kraja, ali mo\u017ee\u0161 prekinuti vezu putem unsubscribe.<\/p>\n<p><\/p>\n<p>\u017delio bih napomenuti da postoje takozvani topli tokovi (ovakvo se odre\u0111ivanje rijetko susre\u0107e, i to samo u stranim zajednicama) \u2014 to je tok koji se transformira iz hladnog u vru\u0107i. Postavlja se pitanje \u2014 gdje ga koristiti? Pru\u017eit \u0107u primjer iz prakse.<\/p>\n<p><\/p>\n<p>Radim s Angularom. Aktivno koristi RxJS. Za dobivanje podataka s poslu\u017eitelja o\u010dekujem hladni tok i taj tok koristim u predlo\u0161ku uz pomo\u0107 asyncPipe. Ako koristim ovu cijev nekoliko puta, vra\u0107aju\u0107i se na definiciju hladnog toka, svaka cijev \u0107e zahtijevati podatke s poslu\u017eitelja, \u0161to je blago re\u010deno \u010dudno. A ako transformiram hladni tok u topli, upit \u0107e se izvr\u0161iti samo jednom.<\/p>\n<p><\/p>\n<p>Uop\u0107e, razumijevanje vrsta tokova prili\u010dno je slo\u017eeno za po\u010detnike, ali va\u017eno je. <\/p>\n<p><\/p>\n<h3 id=\"operators\">Operatori<\/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>Mogu\u0107e je pro\u0161iriti mogu\u0107nosti rada s tokovima putem operatora. Oni poma\u017eu u kontroliranju doga\u0111aja koji se odvijaju u Observable-u. Razmotrit \u0107emo nekoliko najpopularnijih, a detaljnije informacije o operatorima mo\u017eete prona\u0107i na vezama u korisnim informacijama.<\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 of<\/strong><\/p>\n<p><\/p>\n<p>Po\u010dnimo s pomo\u0107nim operatorom of. On stvara Observable na temelju jednostavne vrijednosti.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/68f382447e306392b025867a9a1e88e7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 filter<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/24ac65fdb5ccc7f6301b3dfe49f1e804.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Operator filtriranja filter, kao \u0161to se mo\u017ee naslutiti iz naziva, filtrira signal toka. Ako operator vra\u0107a istinu, propu\u0161ta dalje.<\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 take<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/b3e7a2a2e03038d6fc250247ff4496a2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>take \u2014 Prima vrijednost broja emitiranih, nakon \u010dega zavr\u0161ava tok.<\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 debounceTime<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/add686e546a0b6169c38fb3b457da928.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>debounceTime \u2014 odbacuje emitirane vrijednosti koje ulaze u odre\u0111eni vremenski interval izme\u0111u izlaznih podataka \u2014 nakon proteka tog vremenskog intervala emitira posljednju vrijednost.<\/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  \/\/ Emituje vrijednost svake 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n\n  \/\/ Emituje vrijednost svake 1500ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1500);\n}).pipe(\n  debounceTime(700),  \/\/ \u010cekamo 700ms prije obrade vrijednosti\n  take(3)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/dbb690d6fea6c43c1f0a2bdabea57934.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 takeWhile<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/120d9fe6ddf5a60ddffc8742989b27ff.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Emitira vrijednosti sve dok takeWhile ne vrati false, nakon \u010dega se odjavljuje od toka.<\/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  \/\/ Emitira vrijednost svakih 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=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/d2910d1bf9fab228acc9241fdbad3d4a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 combineLatest<\/strong><\/p>\n<p><\/p>\n<p>Kombinirani operator combineLatest je nalik promise.all. Spaja nekoliko tokova u jedan. Nakon \u0161to svaki tok izvr\u0161i barem jednu emitaciju, dobijamo posljednje vrijednosti iz svakog u obliku niza. Zatim, nakon bilo koje emitacije iz spojenih tokova, vratit \u0107e nove vrijednosti.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, 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  \/\/ Emitira vrijednost svakih 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  \/\/ Emitira vrijednost svakih 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=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/7fc35461f446987ef81302ff7c2ed5a8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 zip<\/strong><\/p>\n<p><\/p>\n<p>Zip \u010deka vrijednost iz svakog toka i formira niz na temelju tih vrijednosti. Ako vrijednost ne do\u0111e iz nekog toka, grupa ne\u0107e biti formirana.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, 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  \/\/ Emitira vrijednost svakih 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  \/\/ Emitira vrijednost svakih 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  \/\/ Emitira vrijednost svakih 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=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/e2606bf8ea5f8a660699ebe896a27d80.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 forkJoin<\/strong><\/p>\n<p><\/p>\n<p>forkJoin tako\u0111er spaja tokove, ali emitira vrijednost samo kada su svi tokovi zavr\u0161eni (complete).<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, 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  \/\/ Emitira vrijednost svakih 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  \/\/ Emitira vrijednost svakih 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  \/\/ Emitira vrijednost svakih 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=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/df110efc7ece46fc1d8da2d7693f75bb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 map<\/strong><\/p>\n<p><\/p>\n<p>Transformacijski operator map pretvara vrijednost emitacije u novu. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, 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  \/\/ Emitira vrijednost svakih 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=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/4e4ff3e2eb4acf69f16559c711a2e666.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operatori \u2013 share, tap<\/strong><\/p>\n<p><\/p>\n<p>Operator tap \u2014 omogu\u0107uje izvo\u0111enje sporednih efekata, odnosno radnje koje ne utje\u010du na sekvencu.<\/p>\n<p><\/p>\n<p>Utentni operator share mo\u017ee pretvoriti hladni tok u vru\u0107i. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asinhrono programiranje u JavaScriptu. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/c46e96420ed78d197ceef829ff74c82d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Zavr\u0161ili smo s operatorima. Prelazimo na Subject.<\/p>\n<p>\n<b class=\"spoiler_title\">Misli na glas<\/b><\/p>\n<p>I tad sam oti\u0161ao piti \u010daj. Umorili su me ti primjeri \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">Obitelj subject-a<\/h2>\n<p><\/p>\n<p>Obitelj subject-a je izvrstan primjer vru\u0107ih tokova. Ove klase su neka vrsta hibrida koje istovremeno djeluju kao observable i observer. Budu\u0107i da je subject vru\u0107i tok, potrebno je otkazati pretplatu. \u0160to se ti\u010de osnovnih metoda, to su:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 prijenos novih podataka u tok<\/li>\n<li>error \u2013 gre\u0161ka i zavr\u0161etak toka<\/li>\n<li>complete \u2013 zavr\u0161etak toka<\/li>\n<li>subscribe \u2013 pretplatiti se na tok<\/li>\n<li>unsubscribe \u2013 odjaviti se s toka<\/li>\n<li>asObservable \u2013 pretvoriti u promatra\u010da<\/li>\n<li>toPromise \u2013 pretvara u promisu<\/li>\n<\/ul>\n<p><\/p>\n<p>Isti\u010de se 4 do 5 vrsta subject-a. <\/p>\n<p>\n<b class=\"spoiler_title\">Misli na glas<\/b><\/p>\n<p>Na streamu sam govorio o 4, a ispostavilo se da su jo\u0161 jedan dodali. Kako se ka\u017ee, \u017eivite i u\u010dite.<\/p>\n<p><\/p>\n<p>Jednostavni Subject <code>new Subject()<\/code>\u2013 najjednostavnija vrsta subject-a. Stvara se bez parametara. Prenosi vrijednosti koje dolaze samo nakon pretplate.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject( defaultData )<\/code> \u2013 po mom mi\u0161ljenju naj\u010de\u0161\u0107e kori\u0161tena vrsta subject-a. Prima zadanu vrijednost. Uvijek \u010duva podatke posljednjeg emitiranja koje \u0161alje prilikom pretplate. Ova klasa tako\u0111e ima koristan metod value, koji vra\u0107a trenutno stanje toka.<\/p>\n<p><\/p>\n<p>ReplaySubject <code>new ReplaySubject(bufferSize?: number, windowTime?: number)<\/code> \u2013 mo\u017ee opcionalno primiti kao prvi argument veli\u010dinu spremnika vrijednosti koje \u0107e \u010duvati, a kao drugi vrijeme tijekom kojeg su potrebne promjene.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> \u2013 prilikom pretplate ni\u0161ta se ne doga\u0111a i vrijednost \u0107e biti vra\u0107ena samo prilikom complete. Vra\u0107a se samo posljednja vrijednost toka.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig | Observable, destination?: Observer)<\/code> \u2013 o njemu dokumentacija \u0161uti i ja ga prvi put vidim. Tko zna \u0161to radi, javite se, dopunit \u0107emo.<\/p>\n<p><\/p>\n<p>Uf. Pa, obradili smo sve \u0161to sam htio danas re\u0107i. Nadam se da su informacije bile korisne. Samostalno se mo\u017eete informirati o popisu literature u kartici korisne informacije.<\/p>\n<p><\/p>\n<h2 id=\"poleznaya-informaciya\">Korisne informacije<\/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 na stream<\/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 Kako radi JS: pregled motora, mehanizama izvr\u0161enja, stoga poziva<\/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 Kako funkcionira JS: doga\u0111ajna petlja, asinkronost i pet na\u010dina za pobolj\u0161anje koda s async \/ await<\/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 Kako funkcionira Event Loop u JavaScriptu<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/tproger.ru\/translations\/asynchronous-javascript\/\">https:\/\/tproger.ru\/translations\/asynchronous-javascript\/<\/a><\/noindex> \u2014 Evolucija asinkronog JavaScript-a<\/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 \u0160to je RxJS i za\u0161to je korisno to znati<\/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 Prakti\u010dna primjena RxJS-a<\/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 Observables Tutorial \u2014 Kreiranje &amp; Prijavljivanje na Observables<\/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: Vru\u0107e i Hladne Observables<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FiPgB\">https:\/\/clck.ru\/FiPgB<\/a><\/noindex> \u2014 Klase, funkcije za kreiranje Observable. Operatori.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.learnrxjs.io\/operators\/\">https:\/\/www.learnrxjs.io\/operators\/<\/a><\/noindex> \u2014 RxJS operatori kroz primjere<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/rxjs.dev\/api\">https:\/\/rxjs.dev\/api<\/a><\/noindex> \u2014 Popis API-ja<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FkS8Y\">https:\/\/clck.ru\/FkS8Y<\/a><\/noindex> \u2014 Vrste Subject-a i Planovi u RxJS-u<\/li>\n<\/ul>\n<p>Izvor: <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.4 - 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\/hr\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\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\/hr\/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\udd47Asinkrono programiranje u JavaScriptu. ( Callback, Promise, RxJs ) | ProHoster","description":"Pozdrav svima. Ovde je Sergej Omelnitzki. Nedavno sam imao stream o reaktivnom programiranju, gde sam pri\u010dao o asinhronosti u JavaScriptu. Danas bih \u017eeleo da sa\u017emem ovaj materijal.","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"hr_HR","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\/hr\/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\/hr\/wp-json\/wp\/v2\/posts\/36774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=36774"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/36774\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/27545"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=36774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=36774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=36774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}