{"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\/ro\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","title":{"rendered":"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Salut tuturor. Sunt Oleinik Sergey. Recent am avut un stream despre programarea reactiv\u0103, unde am vorbit despre asincronismul din JavaScript. Ast\u0103zi a\u0219 dori s\u0103 rezum acest material. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/11acf6af8328d3deb6f0ce48e813efb7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Dar \u00eenainte de a \u00eencepe materialul principal, trebuie s\u0103 facem o introducere. A\u0219adar, s\u0103 \u00eencepem cu defini\u021biile: ce este un stiv\u0103 \u0219i o coad\u0103?<br \/>\n<strong>Stiv\u0103 <\/strong>\u2014 este o colec\u021bie ale c\u0103rei elemente sunt ob\u021binute pe principiul \u201eultimul intrat, primul ie\u0219it\u201d LIFO<br \/>\n<strong>Coad\u0103 <\/strong>\u2014 este o colec\u021bie ale c\u0103rei elemente sunt ob\u021binute pe principiul \u201eprimul intrat, primul ie\u0219it\u201d FIFO<\/p>\n<p><\/p>\n<p>Bine, s\u0103 continu\u0103m. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a7d64d1c74f37b463869dd57b96c9d0e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>JavaScript este un limbaj de programare pe un singur fir de execu\u021bie. Aceasta \u00eenseamn\u0103 c\u0103 are un singur fir de execu\u021bie \u0219i o singur\u0103 stiv\u0103, \u00een care func\u021biile sunt a\u0219ezate \u00een a\u0219teptare pentru execu\u021bie. Prin urmare, \u00eentr-un singur moment, JavaScript poate executa doar o singur\u0103 opera\u021bie, iar celelalte opera\u021bii a\u0219teapt\u0103 s\u0103 fie procesate \u00een stiv\u0103 p\u00e2n\u0103 c\u00e2nd sunt apelate. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Stiva de apeluri<\/strong> \u2014 este o structur\u0103 de date care, simplificat, \u00eenregistreaz\u0103 informa\u021bii despre locul din program unde ne afl\u0103m. Dac\u0103 intr\u0103m \u00eentr-o func\u021bie, ad\u0103ug\u0103m un record despre aceasta \u00een partea de sus a stivei. C\u00e2nd ne \u00eentoarcem din func\u021bie, scoatem din stiv\u0103 cel mai de sus element \u0219i ne reg\u0103sim acolo de unde am apelat acea func\u021bie. Aceasta este tot ce poate face o stiv\u0103. Dar acum apare o \u00eentrebare foarte interesant\u0103. Cum func\u021bioneaz\u0103 atunci asincronismul \u00een JavaScript?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a29fd1dd3de06fb203c7dd14bda30548.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>De fapt, pe l\u00e2ng\u0103 stiv\u0103, \u00een browsere exist\u0103 o coad\u0103 special\u0103 pentru lucrul cu a\u0219a-numitul WebAPI. Func\u021biile din aceast\u0103 coad\u0103 vor fi executate \u00een ordinea \u00een care sunt ad\u0103ugate doar dup\u0103 ce stiva este complet eliberat\u0103. Numai dup\u0103 aceea sunt mutate din coad\u0103 \u00een stiv\u0103 pentru execu\u021bie. Dac\u0103 \u00een stiv\u0103 exist\u0103 m\u0103car un element, acestea nu pot s\u0103 intre \u00een stiv\u0103. Din acest motiv, apelurile func\u021biilor cu timeout sunt adesea inexacte ca timp, deoarece func\u021bia nu poate intra din coad\u0103 \u00een stiv\u0103, c\u00e2t timp aceasta este plin\u0103. <\/p>\n<p><\/p>\n<p>S\u0103 lu\u0103m urm\u0103torul exemplu \u0219i s\u0103 ne ocup\u0103m de \u201eexecu\u021bia\u201d lui pas cu pas. De asemenea, s\u0103 vedem ce se \u00eent\u00e2mpl\u0103 \u00een sistem \u00een acela\u0219i timp.<\/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=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/379423fca95fb28b2124be03dfd15739.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>1) Deocamdat\u0103 nu se \u00eent\u00e2mpl\u0103 nimic. Consola browserului este goal\u0103, stiva de apeluri este liber\u0103.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/4a16bbc23bade54ae0b02d81d5f6a581.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>2) Apoi, comanda console.log('Hi') este ad\u0103ugat\u0103 \u00een stiva apelurilor.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a1845af23fd7dedebf94afc168f1f13f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>3) \u0218i aceasta se execut\u0103<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/57397b53386018b662f3a79a6d4d60fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>4) Apoi, console.log('Hi') este eliminat\u0103 din stiva apelurilor.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/7cb2b32be8807ecf39d2f38683ccd435.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>5) Acum trecem la comanda setTimeout(function cb1() {\u2026 }). Aceasta este ad\u0103ugat\u0103 \u00een stiva de apeluri.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/99c0724994e3390d009577852b451beb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>6) Comanda setTimeout(function cb1() {\u2026 }) se execut\u0103. Browserul creeaz\u0103 un timer, care face parte din Web API. Acesta va \u00eencepe un contor \u00eenapoi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/99086cdeafd83c5fe72e92c4a9f9b738.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>7) Comanda setTimeout(function cb1() {\u2026 }) a terminat \u0219i este eliminat\u0103 din stiva de apeluri.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/24ac12b1b6cfbff780ece9e9a7acd7c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>8) Comanda console.log('Bye') este ad\u0103ugat\u0103 \u00een stiva apelurilor.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/6ccad0ad8eebf05e870a409766d38766.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>9) Comanda console.log('Bye') este executat\u0103.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/09e4e380eb873fb23bea550f3ffb21f7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>10) Comanda console.log('Bye') este eliminat\u0103 din stiva apelurilor.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/357bfb372361310681ba7bb1860d90d7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>11) Dup\u0103 ce au trecut cel pu\u021bin 5000 ms, timerul terminateaz\u0103 \u0219i plaseaz\u0103 callback-ul cb1 \u00een coada de callback-uri.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/8170e8ff5d3d0c56c0091658370c25cc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>12) Ciclul de evenimente ia func\u021bia cb1 din coada de callback-uri \u0219i o plaseaz\u0103 \u00een stiva de apeluri.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/d858a54e82bc32d84f854610db462bc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>13) Func\u021bia cb1 este executat\u0103 \u0219i adaug\u0103 console.log('cb1') \u00een stiva apelurilor.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/6ca8e016389904eec57035e64d57a157.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>14) Comanda console.log('cb1') este executat\u0103.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/0caa645a90ac1fca5fb8a76569494d48.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>15) Comanda console.log('cb1') este eliminat\u0103 din stiva apelurilor.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/aeb838fe8df3f6e3f8603a4207a6e193.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>16) Func\u021bia cb1 este eliminat\u0103 din stiva de apeluri.<\/p>\n<p><\/p>\n<p>S\u0103 ne uit\u0103m la un exemplu \u00een dinamic\u0103:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/3836d9df513afee374f498720990e39f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Iat\u0103, am discutat despre cum asynchronicitatea este implementat\u0103 \u00een JavaScript. Acum s\u0103 vorbim pe scurt despre evolu\u021bia codului asincron.<\/p>\n<p><\/p>\n<h2 id=\"evolyuciya-asinhronnogo-koda\">Evolu\u021bia codului asincron.<\/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>Programarea asincron\u0103, a\u0219a cum o \u0219tim \u00een JavaScript, poate fi realizat\u0103 doar prin func\u021bii. Acestea pot fi transmise ca orice alt\u0103 variabil\u0103 altor func\u021bii. Astfel au ap\u0103rut callback-urile. \u0218i este grozav, distractiv \u0219i plin de via\u021b\u0103, p\u00e2n\u0103 c\u00e2nd devine trist, melancolic \u0219i deprimant. De ce? E simplu:<\/p>\n<p><\/p>\n<ul>\n<li>Pe m\u0103sur\u0103 ce complexitatea codului cre\u0219te, proiectul se transform\u0103 rapid \u00een blocuri de cod greu de \u00een\u021beles, mult \u00eenvelite - \u00abcallback hell\u00bb.<\/li>\n<li>Gestionarea erorilor poate fi u\u0219or omis\u0103.<\/li>\n<li>Nu po\u021bi returna expresii cu return.<\/li>\n<\/ul>\n<p><\/p>\n<p>Odat\u0103 cu apari\u021bia Promise, situa\u021bia s-a \u00eembun\u0103t\u0103\u021bit pu\u021bin.<\/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('FAILED 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>Au ap\u0103rut lan\u021buri de promisiuni, ceea ce a \u00eembun\u0103t\u0103\u021bit lizibilitatea codului.<\/li>\n<li>A ap\u0103rut o metod\u0103 separat\u0103 pentru interceptarea erorilor.<\/li>\n<li>A ap\u0103rut posibilitatea execut\u0103rii paralele cu ajutorul Promise.all<\/li>\n<li>Putem rezolva asincronicitatea imbricat\u0103 cu ajutorul async\/await<\/li>\n<\/ul>\n<p><\/p>\n<p>Dar promisiunea are limit\u0103rile sale. De exemplu, o promisiune nu poate fi anulat\u0103 f\u0103r\u0103 ceva efort, iar, ceea ce e cel mai important \u2013 lucreaz\u0103 cu o singur\u0103 valoare.<\/p>\n<p><\/p>\n<p>Ei bine, iat\u0103 c\u0103 ne-am apropiat u\u0219or de programarea reactiv\u0103. E\u0219ti obosit? Dar, \u00een bun\u0103 m\u0103sur\u0103, po\u021bi s\u0103 mergi s\u0103 \u00ee\u021bi prepari o can\u0103 de ceai, s\u0103 te g\u00e2nde\u0219ti \u0219i s\u0103 te \u00eentorci s\u0103 continui citirea. Eu voi continua.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/48409ec625d57fec171214c1de332c85.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Programarea reactiv\u0103<\/strong>\u2013 o paradigm\u0103 de programare orientat\u0103 pe fluxurile de date \u0219i propagarea schimb\u0103rilor. S\u0103 analiz\u0103m mai \u00een detaliu ce \u00eenseamn\u0103 fluxul de date.<\/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>S\u0103 presupunem c\u0103 avem un c\u00e2mp de input. Cre\u0103m un array \u0219i la fiecare eveniment de keyup al input-ului vom salva evenimentul \u00een array-ul nostru. De asemenea, ar fi de notat c\u0103 array-ul nostru este sortat cronologic, adic\u0103 indexul evenimentelor mai recente este mai mare dec\u00e2t indexul celor mai vechi. Acest array reprezint\u0103 un model simplificat al unui flux de date, dar este \u00eenc\u0103 departe de a fi un flux. Pentru ca acest array s\u0103 poat\u0103 fi numit un flux, el trebuie s\u0103 fie capabil s\u0103 notifice abona\u021bii atunci c\u00e2nd primesc date noi. Astfel, am ajuns la defini\u021bia fluxului.<\/p>\n<p><\/p>\n<h3 id=\"potok-dannyh\">Flux de date<\/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=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/68ec447abafb6b8a323b429ed94f8252.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Fluxul<\/strong>\u2013 este un array de date, sortat cronologic, care poate comunica c\u00e2nd datele s-au schimbat. Acum imagineaz\u0103-\u021bi c\u00e2t de convenabil devine s\u0103 scrii cod \u00een care pentru o singur\u0103 ac\u021biune trebuie s\u0103 apelezi mai multe evenimente \u00een diferite locuri din cod. Pur \u0219i simplu ne abon\u0103m la flux \u0219i acesta ne va informa singur c\u00e2nd vor avea loc schimb\u0103ri. \u0218i asta poate face biblioteca RxJs.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/dcb1cfca8b4d8a887b63c302a7d6c06a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>RxJS <\/strong> \u2013 este o bibliotec\u0103 pentru lucrul cu programe asincrone \u0219i bazate pe evenimente care folosesc secven\u021be observabile. Biblioteca ofer\u0103 tipul principal <em>Observable<\/em>, mai multe tipuri auxiliare (<em>Observer, Schedulers, Subjects<\/em>) \u0219i operatori pentru a lucra cu evenimente ca \u0219i cu colec\u021bii (<em>map, filter, reduce, every<\/em> \u0219i similare din JavaScript Array).<\/p>\n<p><\/p>\n<p>S\u0103 ne familiariz\u0103m cu conceptele de baz\u0103 ale acestei biblioteci.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable \u2014 primul tip de baz\u0103 pe care \u00eel vom examina. Aceast\u0103 clas\u0103 con\u021bine cea mai mare parte a implement\u0103rii RxJs. Este legat\u0103 de un flux observabil, la care se poate abona prin metoda subscribe.<\/p>\n<p><\/p>\n<p>\u00cen Observable se implementeaz\u0103 un mecanism auxiliar pentru a crea actualiz\u0103ri, numit <em>Observer<\/em>. Sursa valorilor pentru Observer este numit\u0103 <em>Producer<\/em>. Aceasta poate fi un array, un iterator, un socket web, un anumit eveniment etc. A\u0219adar, se poate spune c\u0103 observable este un mediator \u00eentre Producer \u0219i Observer. <\/p>\n<p><\/p>\n<p>Observable proceseaz\u0103 trei tipuri de evenimente pentru Observer:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 date noi<\/li>\n<li>error \u2013 o eroare, dac\u0103 secven\u021ba s-a \u00eencheiat din cauza unei situa\u021bii excep\u021bionale. Acest eveniment presupune de asemenea terminarea secven\u021bei.<\/li>\n<li>complete \u2014 un semnal de finalizare a secven\u021bei. Asta \u00eenseamn\u0103 c\u0103 nu vor mai fi date noi.<\/li>\n<\/ul>\n<p><\/p>\n<p>S\u0103 vedem o demonstra\u021bie:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c5bcd2af0f18b6de3ab0dbc20db595d1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>La \u00eenceput, vom procesa valorile 1, 2, 3, iar dup\u0103 1 secund\u0103, vom ob\u021bine 4 \u0219i vom \u00eencheia fluxul nostru.<\/p>\n<p>\n<b class=\"spoiler_title\">G\u00e2nduri cu voce tare<\/b><\/p>\n<p>\u0218i atunci mi-am dat seama c\u0103 era mai interesant s\u0103 povestesc dec\u00e2t s\u0103 scriu despre asta. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Subscription<\/h3>\n<p><\/p>\n<p>C\u00e2nd ne abona\u021bi la flux, cre\u0103m o nou\u0103 clas\u0103 de <strong>subscription<\/strong>, care ne ofer\u0103 posibilitatea de a anula abonarea prin metoda <em>unsubscribe<\/em>. De asemenea, putem grupa abonarile prin metoda <em>add<\/em>. Este logic c\u0103 putem dezgrupa fluxurile prin <em>remove<\/em>. Metodele add \u0219i remove primesc ca intrare o alt\u0103 subscriere. A\u0219 dori s\u0103 subliniez c\u0103 atunci c\u00e2nd ne dezabon\u0103m, ne dezabon\u0103m de la toate subscrierile copil, ca \u0219i cum am fi apelat metoda unsubscribe pentru ele. S\u0103 continu\u0103m.<\/p>\n<p><\/p>\n<h3 id=\"vidy-potokov\">Tipuri de fluxuri<\/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 este creat din afara observable<\/td>\n<td>Producer este creat \u00een interiorul observable<\/td>\n<\/tr>\n<tr>\n<td>Datele sunt transmise \u00een momentul cre\u0103rii observable<\/td>\n<td>Datele sunt comunicate \u00een momentul abon\u0103rii<\/td>\n<\/tr>\n<tr>\n<td>Este necesar\u0103 o logic\u0103 suplimentar\u0103 pentru dezabonare<\/td>\n<td>Fluxul se \u00eencheie de la sine<\/td>\n<\/tr>\n<tr>\n<td>Utilizeaz\u0103 o rela\u021bie de tip unul-la-mul\u021bi<\/td>\n<td>Utilizeaz\u0103 o rela\u021bie de tip unul-la-unul<\/td>\n<\/tr>\n<tr>\n<td>Toate abon\u0103rile au o valoare comun\u0103<\/td>\n<td>Abon\u0103rile sunt independente<\/td>\n<\/tr>\n<tr>\n<td>Datele pot fi pierdute dac\u0103 nu exist\u0103 abonare<\/td>\n<td>Reemite toate valorile fluxului pentru o nou\u0103 abonare<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Dac\u0103 ar fi s\u0103 fac o analogie, a\u0219 imagina un flux cald ca un film \u00eentr-un cinematograf. \u00cen momentul \u00een care ai venit, aceea e clipa \u00een care \u00eencepi vizionarea. Un flux rece l-a\u0219 compara cu un apel la asisten\u021ba tehnic\u0103. Oricine sun\u0103 ascult\u0103 \u00eenregistrarea unui r\u0103spuns automat de la \u00eenceput p\u00e2n\u0103 la sf\u00e2r\u0219it, dar po\u021bi renun\u021ba la apel folosind unsubscribe.<\/p>\n<p><\/p>\n<p>A\u0219 dori s\u0103 men\u021bionez c\u0103 exist\u0103 a\u0219a-numitele fluxuri calde (aceast\u0103 defini\u021bie am \u00eent\u00e2lnit-o foarte rar \u0219i doar \u00een comunit\u0103\u021bi externe) \u2014 este un flux care se transform\u0103 dintr-un flux rece \u00eentr-un flux cald. Se ridic\u0103 \u00eentrebarea \u2014 unde ar trebui s\u0103 le folosim)) Voi da un exemplu din practic\u0103.<\/p>\n<p><\/p>\n<p>Lucrez cu Angular. Acesta folose\u0219te activ rxjs. Pentru a ob\u021bine date de la server, a\u0219tept un flux rece \u0219i folosesc acest flux \u00een \u0219ablon cu ajutorul asyncPipe. Dac\u0103 folosesc acest pipe de mai multe ori, atunci, referindu-m\u0103 la defini\u021bia fluxului rece, fiecare pipe va solicita date de la server, ceea ce, pe scurt, este bizar. Dar dac\u0103 transform un flux rece \u00eentr-unul cald, atunci cererea se va face o singur\u0103 dat\u0103.<\/p>\n<p><\/p>\n<p>De fapt, \u00een\u021belegerea formelor de fluxuri este destul de complicat\u0103 pentru \u00eencep\u0103tori, dar este important\u0103. <\/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>Oportunit\u0103\u021bile de a lucra cu fluxurile ne sunt oferite de operatori. Ace\u0219tia ajut\u0103 la controlul evenimentelor care se desf\u0103\u0219oar\u0103 \u00een Observable. Vom analiza c\u00e2\u021biva dintre cei mai populari, iar informa\u021bii mai detaliate despre operatori pute\u021bi g\u0103si \u00een linkurile din informa\u021biile utile.<\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 of<\/strong><\/p>\n<p><\/p>\n<p>S\u0103 \u00eencepem cu operatorul auxiliar of. Acesta creeaz\u0103 un Observable pe baza unei valori simple.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, 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=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/24ac65fdb5ccc7f6301b3dfe49f1e804.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Operatorul de filtrare filter, a\u0219a cum se poate \u00een\u021belege din nume, filtreaz\u0103 semnalul fluxului. Dac\u0103 operatorul returneaz\u0103 adev\u0103rat, atunci trece mai departe.<\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 take<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/b3e7a2a2e03038d6fc250247ff4496a2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>take \u2014 Prime\u0219te valoarea num\u0103rului de emisii, dup\u0103 care \u00eencheie fluxul.<\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 debounceTime<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/add686e546a0b6169c38fb3b457da928.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>debounceTime \u2014 elimin\u0103 valorile emise care apar \u00een intervalul specificat de timp \u00eentre ie\u0219irile date \u2014 dup\u0103 expirarea intervalului de timp emite ultima valoare.<\/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  \/\/ Emit value every 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n\n  \/\/ Emit value every 1500ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1500);\n}).pipe(\n  debounceTime(700),  \/\/ Wait for 700ms before processing values\n  take(3)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/dbb690d6fea6c43c1f0a2bdabea57934.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operators \u2014 takeWhile<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/120d9fe6ddf5a60ddffc8742989b27ff.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Emite valori p\u00e2n\u0103 c\u00e2nd takeWhile returneaz\u0103 false, dup\u0103 care se dezaboneaz\u0103 de la flux.<\/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=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, 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>Operatorul combinat combineLatest este similar cu promise.all. Acesta combin\u0103 mai multe fluxuri \u00eentr-unul. Dup\u0103 ce fiecare flux emite m\u0103car o dat\u0103, ob\u021binem ultimele valori de la fiecare sub form\u0103 de masiv. Ulterior, dup\u0103 orice emitere din fluxurile combinate, vor fi furnizate noi valori.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, 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=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, 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 a\u0219teapt\u0103 valori din fiecare flux \u0219i formeaz\u0103 un masiv pe baza acestor valori. Dac\u0103 o valoare nu vine dintr-un flux, grupul nu va fi format.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, 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=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, 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 combin\u0103 de asemenea fluxurile, dar emite o valoare doar atunci c\u00e2nd toate fluxurile sunt completate.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, 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  \/\/ Emitem o valoare la fiecare 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  \/\/ Emitem o valoare la fiecare 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  \/\/ Emitem o valoare la fiecare 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=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/df110efc7ece46fc1d8da2d7693f75bb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operatorii \u2014 map<\/strong><\/p>\n<p><\/p>\n<p>Operatorul de transformare map converteste valoarea emisiunii \u00eentr-o nou\u0103 valoare. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, 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  \/\/ Emitem o valoare la fiecare 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=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/4e4ff3e2eb4acf69f16559c711a2e666.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operatorii \u2013 share, tap<\/strong><\/p>\n<p><\/p>\n<p>Operatorul tap \u2013 permite realizarea de efecte secundare, adic\u0103 orice ac\u021biuni care nu influen\u021beaz\u0103 secven\u021ba.<\/p>\n<p><\/p>\n<p>Operatorul utilitar share poate transforma un flux rece \u00eentr-unul cald. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programarea asincron\u0103 \u00een JavaScript. (Callback, Promisiune, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c46e96420ed78d197ceef829ff74c82d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Am terminat cu operatorii. S\u0103 trecem la Subject.<\/p>\n<p>\n<b class=\"spoiler_title\">G\u00e2nduri cu voce tare<\/b><\/p>\n<p>\u0218i aici am plecat s\u0103 beau ceai. M-au obosit aceste exemple \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">Familia subject-urilor<\/h2>\n<p><\/p>\n<p>Familia subject-urilor reprezint\u0103 un exemplu izbitor de fluxuri calde. Aceste clase reprezint\u0103 un hibrid, care func\u021bioneaz\u0103 simultan ca observable \u0219i observer. Deoarece subject este un flux cald, trebuie s\u0103 te dezabonezi de la el. Vorbind despre metodele principale, acestea sunt:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 transmiterea de noi date \u00een flux<\/li>\n<li>error \u2013 eroare \u0219i \u00eencheierea fluxului<\/li>\n<li>complete \u2013 \u00eencheierea fluxului<\/li>\n<li>subscribe \u2013 a te abona la flux<\/li>\n<li>unsubscribe \u2013 a te dezabona de la flux<\/li>\n<li>asObservable \u2013 transform\u0103m \u00eentr-un observer<\/li>\n<li>toPromise \u2013 transform\u0103 \u00eentr-un promisiune<\/li>\n<\/ul>\n<p><\/p>\n<p>Se disting 4-5 tipuri de subject-uri. <\/p>\n<p>\n<b class=\"spoiler_title\">G\u00e2nduri cu voce tare<\/b><\/p>\n<p>\u00cen stream am spus 4, dar se pare c\u0103 au ad\u0103ugat \u00eenc\u0103 unul. A\u0219a cum se spune, tr\u0103ie\u0219te \u0219i \u00eenva\u021b\u0103.<\/p>\n<p><\/p>\n<p>Subject simplu <code>new Subject()<\/code>\u2013 cea mai simpl\u0103 form\u0103 de subject-uri. Se creeaz\u0103 f\u0103r\u0103 parametri. Transmite valori primite doar dup\u0103 abonare.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject(defaultData)<\/code> \u2013 din punctul meu de vedere, cel mai comun tip de subject-uri. Accept\u0103 o valoare implicit\u0103. P\u0103streaz\u0103 \u00eentotdeauna datele ultimei emisii, pe care le transmite la abonare. Aceast\u0103 clas\u0103 are de asemenea metode utile, cum ar fi value, care returneaz\u0103 valoarea curent\u0103 a fluxului.<\/p>\n<p><\/p>\n<p>ReplaySubject <code>new ReplaySubject(bufferSize?: number, windowTime?: number)<\/code> \u2013 poate accepta op\u021bional ca prim argument dimensiunea buffer-ului valorilor pe care le va re\u021bine \u0219i ca al doilea argument timpul \u00een care avem nevoie de modific\u0103ri.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> \u2014 la \u00eenscriere nimic nu se \u00eent\u00e2mpl\u0103, iar valoarea va fi returnat\u0103 doar la complete. Va fi returnat\u0103 doar ultima valoare din flux.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig | Observable, destination?: Observer)<\/code> \u2014 Despre el documenta\u021bia nu spune nimic \u0219i eu \u00eel v\u0103d pentru prima dat\u0103. Cine \u0219tie ce face, scrie\u021bi-ne, s\u0103 complet\u0103m.<\/p>\n<p><\/p>\n<p>Uf, iat\u0103 c\u0103 am acoperit tot ce voiam s\u0103 discut ast\u0103zi. Sper c\u0103 informa\u021biile de mai sus au fost utile. Po\u021bi consulta singur lista de literatur\u0103 \u00een sec\u021biunea de informa\u021bii utile.<\/p>\n<p><\/p>\n<h2 id=\"poleznaya-informaciya\">Informa\u021bii utile<\/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> \u2014 link c\u0103tre 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> \u2014 Cum func\u021bioneaz\u0103 JS: o privire de ansamblu asupra motorului, mecanismelor de execu\u021bie, stivei de apeluri<\/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 Cum func\u021bioneaz\u0103 JS: ciclul de evenimente, asincronicitatea \u0219i cinci metode de \u00eembun\u0103t\u0103\u021bire a codului cu 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 Cum func\u021bioneaz\u0103 Event Loop \u00een JavaScript<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/tproger.ru\/translations\/asynchronous-javascript\/\">https:\/\/tproger.ru\/translations\/asynchronous-javascript\/<\/a><\/noindex> \u2014 Evolu\u021bia JavaScript-ului asincron<\/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 Ce este RxJS \u0219i de ce este util s\u0103 \u0219tim despre el<\/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 Aplicarea practic\u0103 a 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 Observables Tutorial \u2014 Crearea \u0219i abonarea la 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: Observables fierbin\u021bi \u0219i reci<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FiPgB\">https:\/\/clck.ru\/FiPgB<\/a><\/noindex> \u2014 Clase, func\u021bii pentru crearea Observable. Operatori.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.learnrxjs.io\/operators\/\">https:\/\/www.learnrxjs.io\/operators\/<\/a><\/noindex> \u2014 Operatori RxJS prin exemple<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/rxjs.dev\/api\">https:\/\/rxjs.dev\/api<\/a><\/noindex> \u2014 Lista API<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FkS8Y\">https:\/\/clck.ru\/FkS8Y<\/a><\/noindex> \u2014 Tipuri de Subject \u0219i Program\u0103ri \u00een RxJS<\/li>\n<\/ul>\n<p>Sursa: <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.2 - 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\/ro\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"ro_RO\" \/>\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\/ro\/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\udd47Programare asincron\u0103 \u00een JavaScript. (Callback, Promise, RxJs) | ProHoster","description":"Salut tuturor. Sunt Oleinik Sergey. Recent am avut un stream despre programarea reactiv\u0103, unde am vorbit despre asincronismul din JavaScript. Ast\u0103zi a\u0219 dori s\u0103 rezum acest material.","canonical_url":"https:\/\/prohoster.info\/ro\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"ro_RO","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\/ro\/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\/ro\/wp-json\/wp\/v2\/posts\/36774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/comments?post=36774"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/posts\/36774\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media\/27545"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/media?parent=36774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/categories?post=36774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/ro\/wp-json\/wp\/v2\/tags?post=36774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}