{"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\/da\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","title":{"rendered":"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Hej alle sammen. Det er Omelnitsky Sergey her. For nylig havde jeg en stream om reaktiv programmering, hvor jeg talte om asynkronitet i JavaScript. I dag vil jeg gerne opsummere dette materiale. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/11acf6af8328d3deb6f0ce48e813efb7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Men f\u00f8r vi g\u00e5r i gang med hovedmaterialet, skal vi lave en introduktion. S\u00e5 lad os starte med definitioner: hvad er en stak og en k\u00f8?<br \/>\n<strong>Stak <\/strong>\u2014 er en samling, hvis elementer bliver hentet efter princippet 'sidst ind, f\u00f8rst ud' LIFO<br \/>\n<strong>K\u00f8 <\/strong>\u2014 er en samling, hvis elementer bliver hentet efter princippet ('f\u00f8rst ind, f\u00f8rst ud' FIFO<\/p>\n<p><\/p>\n<p>Okay, lad os forts\u00e6tte. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a7d64d1c74f37b463869dd57b96c9d0e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>JavaScript er et enkelttr\u00e5det programmeringssprog. Det betyder, at der kun er \u00e9n udf\u00f8relsestr\u00e5d og \u00e9n stak, hvor funktioner bliver sat i k\u00f8 til udf\u00f8relse. Derfor kan JavaScript kun udf\u00f8re \u00e9n operation ad gangen, mens de andre operationer venter i stakken, indtil de bliver kaldt. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Stak af kald<\/strong> \u2014 er en dataramme, der forenklet sagt gemmer oplysninger om, hvor vi befinder os i programmet. Hvis vi g\u00e5r ind i en funktion, placerer vi en post om den \u00f8verst i stakken. N\u00e5r vi vender tilbage fra funktionen, fjerner vi det \u00f8verste element fra stakken og befinder os der, hvor vi kaldte denne funktion fra. Det er alt, hvad stakken kan.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a29fd1dd3de06fb203c7dd14bda30548.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Og nu et meget interessant sp\u00f8rgsm\u00e5l. Hvordan fungerer asynkronitet i JavaScript s\u00e5? <\/p>\n<p><\/p>\n<p>Faktisk, udover stakken, eksisterer der i browsere en s\u00e6rlig k\u00f8 til arbejde med s\u00e5kaldte WebAPI'er. Funktioner fra denne k\u00f8 udf\u00f8res i r\u00e6kkef\u00f8lge, f\u00f8rst efter at stakken er helt t\u00f8mt. F\u00f8rst derefter placeres de fra k\u00f8en til stakken til udf\u00f8relse. Hvis der i stakken i \u00f8jeblikket er mindst \u00e9t element, kan de ikke komme ind i stakken. Det er netop derfor, funktioner med timeout ofte ikke er tidsm\u00e6ssigt pr\u00e6cise, da funktionen ikke kan komme fra k\u00f8en til stakken, mens den er fyldt.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">Lad os overveje f\u00f8lgende eksempel og tage os af dets trin-for-trin 'udf\u00f8relse'. Vi vil ogs\u00e5 se, hvad der sker i systemet.<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/379423fca95fb28b2124be03dfd15739.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>console.log('Hi);\nsetTimeout(function cb1() {\n console.log('cb1');\n}, 5000);\nconsole.log('Bye');<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/4a16bbc23bade54ae0b02d81d5f6a581.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>2) Derefter tilf\u00f8jes kommandoen console.log('Hi') til opkaldsstakken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a1845af23fd7dedebf94afc168f1f13f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>3) Og den udf\u00f8res<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/57397b53386018b662f3a79a6d4d60fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>4) Dern\u00e6st fjernes console.log('Hi') fra opkaldsstakken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/7cb2b32be8807ecf39d2f38683ccd435.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>5) Nu g\u00e5r vi videre til kommandoen setTimeout(function cb1() {\u2026 }). Den tilf\u00f8jes til call-stakken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/99c0724994e3390d009577852b451beb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>6) Kommandoen setTimeout(function cb1() {\u2026 }) udf\u00f8res. Browseren opretter en timer, som er en del af Web API. Den vil udf\u00f8re nedt\u00e6llingen.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/99086cdeafd83c5fe72e92c4a9f9b738.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>7) Kommandoen setTimeout(function cb1() {\u2026 }) er f\u00e6rdig og fjernes fra call-stakken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/24ac12b1b6cfbff780ece9e9a7acd7c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>8) Kommandoen console.log('Bye') tilf\u00f8jes til opkaldsstakken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/6ccad0ad8eebf05e870a409766d38766.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>9) Kommandoen console.log('Bye') udf\u00f8res.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/09e4e380eb873fb23bea550f3ffb21f7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>10) Kommandoen console.log('Bye') fjernes fra opkaldsstakken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/357bfb372361310681ba7bb1860d90d7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>11) Efter mindst 5000 ms er g\u00e5et, afslutter timeren sit arbejde og placerer callback cb1 i callback-k\u00f8en.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/8170e8ff5d3d0c56c0091658370c25cc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>12) Event-loopet tager funktionen cb1 fra callback-k\u00f8en og placerer den i call-stakken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/d858a54e82bc32d84f854610db462bc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>13) Funktionen cb1 udf\u00f8res og tilf\u00f8jer console.log('cb1') til opkaldsstakken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/6ca8e016389904eec57035e64d57a157.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>14) Kommandoen console.log('cb1') udf\u00f8res.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/0caa645a90ac1fca5fb8a76569494d48.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>15) Kommandoen console.log('cb1') fjernes fra opkaldsstakken.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/aeb838fe8df3f6e3f8603a4207a6e193.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>16) Funktionen cb1 fjernes fra call-stakken.<\/p>\n<p><\/p>\n<p>Lad os se p\u00e5 et eksempel i dynamik:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/3836d9df513afee374f498720990e39f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>S\u00e5dan, nu har vi set, hvordan asynkronitet er implementeret i JavaScript. Lad os kort diskutere udviklingen af asynkron kode.<\/p>\n<p><\/p>\n<h2 id=\"evolyuciya-asinhronnogo-koda\">Udviklingen af asynkron kode.<\/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>Asynkront programmering, som vi kender det i JavaScript, kan kun implementeres ved hj\u00e6lp af funktioner. De kan gives som enhver anden variabel til andre funktioner. S\u00e5dan blev callbacks til. Og det er sjovt, livligt og underholdende, indtil det bliver trist, melankolsk og s\u00f8rgeligt. Hvorfor? Jo, alt er enkelt:<\/p>\n<p><\/p>\n<ul>\n<li>Med stigende kompleksitet i koden bliver projektet hurtigt til sv\u00e6re at forst\u00e5 dybt indlejrede blokke \u2014 'callback hell'.<\/li>\n<li>Fejlbehandling kan nemt blive overset.<\/li>\n<li>Du kan ikke returnere udtryk med return.<\/li>\n<\/ul>\n<p><\/p>\n<p>Med fremkomsten af Promises blev situationen lidt bedre.<\/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>Der opstod k\u00e6der af promises, hvilket forbedrede l\u00e6sbarheden af koden<\/li>\n<li>Der kom en separat metode til at opfange fejl<\/li>\n<li>Der er nu mulighed for parallelt udf\u00f8rsel ved hj\u00e6lp af Promise.all<\/li>\n<li>Vi kan l\u00f8se indlejret asynkronitet ved hj\u00e6lp af async\/await<\/li>\n<\/ul>\n<p><\/p>\n<p>Men et l\u00f8fte har sine begr\u00e6nsninger. For eksempel kan et l\u00f8fte ikke annulleres uden nogle tricks, og vigtigst af alt - det arbejder kun med \u00e9n v\u00e6rdi.<\/p>\n<p><\/p>\n<p>N\u00e5, vi er stille og roligt ved at n\u00e6rme os reaktiv programmering. Er du tr\u00e6t? Men heldigvis kan du tage en kop te, t\u00e6nke over det og komme tilbage for at l\u00e6se videre. Jeg forts\u00e6tter.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/48409ec625d57fec171214c1de332c85.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Reaktiv programmering<\/strong>\u200a\u2014\u200aen programmeringsparadigme, der fokuserer p\u00e5 datastreams og \u00e6ndringsformidling. Lad os se n\u00e6rmere p\u00e5, hvad en datastream er.<\/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>Forestil dig, at vi har et inputfelt. Vi opretter et array, og ved hver keyup-h\u00e6ndelse fra inputfeltet vil vi gemme h\u00e6ndelsen i vores array. Det skal bem\u00e6rkes, at vores array er sorteret efter tid, dvs. indekset for senere h\u00e6ndelser er st\u00f8rre end indekset for tidligere h\u00e6ndelser. Et s\u00e5dant array repr\u00e6senterer en forenklet model af en datastream, men det er endnu ikke en stroom. For at dette array sikkert kan kaldes en stream, skal det kunne kommunikere til abonnenterne, n\u00e5r nye data ankommer. S\u00e5 vi er kommet til definitionen af en stream.<\/p>\n<p><\/p>\n<h3 id=\"potok-dannyh\">Datastream<\/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=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/68ec447abafb6b8a323b429ed94f8252.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Stream\u200a<\/strong>\u2014\u200aer et array af data, der er sorteret efter tid, som kan informere om, at dataene er \u00e6ndret. Forestil dig, hvor praktisk det bliver at skrive kode, hvor en handling kr\u00e6ver, at flere h\u00e6ndelser kaldes p\u00e5 forskellige steder i koden. Vi abonnerer blot p\u00e5 str\u00f8mmen, og den vil selv informere os om, hvorn\u00e5r der sker \u00e6ndringer. Dette kan RxJs bibliotekt g\u00f8re.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (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 er et bibliotek til at arbejde med asynkrone og event-baserede programmer ved hj\u00e6lp af observerbare sekvenser. Biblioteket tilbyder den grundl\u00e6ggende type <em>Observable<\/em>, flere hj\u00e6lpefunktioner (<em>Observer, Schedulers, Subjects<\/em>) og operat\u00f8rer til at arbejde med h\u00e6ndelser som samlinger (<em>map, filter, reduce, every<\/em> og lignende fra JavaScript Array).<\/p>\n<p><\/p>\n<p>Lad os se n\u00e6rmere p\u00e5 de grundl\u00e6ggende begreber i dette bibliotek.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable \u2014 den f\u00f8rste grundl\u00e6ggende type, som vi vil se p\u00e5. Denne klasse indeholder den vigtigste del af RxJs-implementeringen. Den er knyttet til en observerbar stream, som man kan abonnere p\u00e5 ved hj\u00e6lp af metoden subscribe.<\/p>\n<p><\/p>\n<p>I Observable implementerer en st\u00f8ttefunktion til at skabe opdateringer, s\u00e5kaldt <em>Observer<\/em>. Kilden til v\u00e6rdierne for Observer kaldes <em>Producer<\/em>. Dette kan v\u00e6re et array, en iterator, en web socket, en begivenhed osv. S\u00e5 man kan sige, at observable fungerer som en formidler mellem Producer og Observer. <\/p>\n<p><\/p>\n<p>Observable h\u00e5ndterer tre typer begivenheder for Observer:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 nye data<\/li>\n<li>error \u2013 en fejl, hvis sekvensen afsluttes p\u00e5 grund af en undtagelsessituation. Denne begivenhed betyder ogs\u00e5, at sekvensen er afsluttet.<\/li>\n<li>complete \u2013 et signal om, at sekvensen er afsluttet. Det betyder, at der ikke vil komme flere nye data.<\/li>\n<\/ul>\n<p><\/p>\n<p>Lad os se en demo:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c5bcd2af0f18b6de3ab0dbc20db595d1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>I starten vil vi behandle v\u00e6rdierne 1, 2, 3, og efter 1 sekund vil vi modtage 4 og afslutte vores str\u00f8m.<\/p>\n<p>\n<b class=\"spoiler_title\">Tankerne h\u00f8jt<\/b><\/p>\n<p>Og her inds\u00e5 jeg, at det var mere interessant at fort\u00e6lle end at skrive om det. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Subscription<\/h3>\n<p><\/p>\n<p>N\u00e5r vi tilmelder os en str\u00f8m, opretter vi en ny klasse <strong>subscription<\/strong>, som giver os mulighed for at afmelde os med metoden <em>unsubscribe<\/em>. Vi kan ogs\u00e5 gruppere abonnementer ved hj\u00e6lp af metoden <em>add<\/em>. Samt, det er logisk, at vi kan afgruppere str\u00f8mme ved hj\u00e6lp af <em>remove<\/em>. Metoderne add og remove tager en anden abonnement som input. Det skal bem\u00e6rkes, at n\u00e5r vi afmelder os, afmelder vi os alle underordnede abonnementer, som om vi ogs\u00e5 havde kaldt metoden unsubscribe p\u00e5 dem. Lad os forts\u00e6tte.<\/p>\n<p><\/p>\n<h3 id=\"vidy-potokov\">Typer af str\u00f8mme<\/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 oprettes uden for observable<\/td>\n<td>Producer oprettes inden for observable<\/td>\n<\/tr>\n<tr>\n<td>Data overf\u00f8res p\u00e5 tidspunktet for oprettelsen af observable<\/td>\n<td>Data gives under tilmelding<\/td>\n<\/tr>\n<tr>\n<td>Der er behov for ekstra logik for at afmelde<\/td>\n<td>Str\u00f8mmen afsluttes af sig selv<\/td>\n<\/tr>\n<tr>\n<td>Bruger en en-til-mange forbindelse<\/td>\n<td>Bruger en en-til-en forbindelse<\/td>\n<\/tr>\n<tr>\n<td>Alle abonnementer har en f\u00e6lles v\u00e6rdi<\/td>\n<td>Abonnementer er uafh\u00e6ngige<\/td>\n<\/tr>\n<tr>\n<td>Data kan g\u00e5 tabt, hvis der ikke er nogen tilmelding<\/td>\n<td>Genudgiver alle v\u00e6rdier fra str\u00f8mmen til et nyt abonnement<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Hvis jeg skulle lave en analogi, ville jeg beskrive en varm str\u00f8m som en film i biografen. Uanset hvorn\u00e5r du ankom, begynder du at se filmen fra det \u00f8jeblik. En kold str\u00f8m ville jeg sammenligne med et opkald til teknisk support. Enhver, der ringer, lytter til auto-svareren fra start til slut, men du kan l\u00e6gge r\u00f8ret p\u00e5 ved hj\u00e6lp af unsubscribe.<\/p>\n<p><\/p>\n<p>Jeg vil gerne bem\u00e6rke, at der ogs\u00e5 findes s\u00e5kaldte varme str\u00f8mme (dette udtryk har jeg kun set sj\u00e6ldent og kun i udenlandske f\u00e6llesskaber) \u2014 det er en str\u00f8m, der omdannes fra en kold str\u00f8m til en varm. Sp\u00f8rgsm\u00e5let opst\u00e5r \u2014 hvor skal det bruges)) Jeg vil give et eksempel fra praksis.<\/p>\n<p><\/p>\n<p>Jeg arbejder med Angular. Den bruger aktivt RxJS. For at hente data fra serveren forventer jeg en kold str\u00f8m, og jeg bruger denne str\u00f8m i skabelonen med asyncPipe. Hvis jeg bruger denne pipe flere gange, s\u00e5, tilbage til definitionen af en kold str\u00f8m, vil hver pipe anmode om data fra serveren, hvilket mildt sagt er underligt. Men hvis jeg omdanner den kolde str\u00f8m til en varm, vil anmodningen ske \u00e9n gang.<\/p>\n<p><\/p>\n<p>Generelt set er forst\u00e5elsen af str\u00f8mmens typer ret vanskelig for begyndere, men den er vigtig. <\/p>\n<p><\/p>\n<h3 id=\"operators\">Operat\u00f8rer<\/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>Operat\u00f8rer udvider vores mulighed for at arbejde med str\u00f8mme. De hj\u00e6lper med at kontrollere de h\u00e6ndelser, der forekommer i Observable. Vi vil se p\u00e5 et par af de mest popul\u00e6re, og mere detaljeret om operat\u00f8rerne kan findes via links i nyttig information.<\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2014 of<\/strong><\/p>\n<p><\/p>\n<p>Lad os starte med hj\u00e6lpeoperat\u00f8ren of. Den skaber en Observable baseret p\u00e5 en simpel v\u00e6rdi.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/68f382447e306392b025867a9a1e88e7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2014 filter<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/24ac65fdb5ccc7f6301b3dfe49f1e804.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Filteroperat\u00f8ren filter, som man kan forst\u00e5 ud fra navnet, filtrerer signalet i str\u00f8mmen. Hvis operat\u00f8ren returnerer sandhed, s\u00e5 sendes det videre.<\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2014 take<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (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 Modtager antallet af emissioner, hvorefter str\u00f8mmen afsluttes.<\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2014 debounceTime<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (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 kasserer de udsendte v\u00e6rdier, der falder inden for den angivne tidsramme mellem udgangsv\u00e6rdierne \u2014 efter et tidsinterval udsendes den sidste v\u00e6rdi.<\/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  \/\/ Udsender v\u00e6rdi hvert 1000 ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n\n  \/\/ Udsender v\u00e6rdi hver 1500 ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1500);\n}).pipe(\n  debounceTime(700),  \/\/ Venter 700 ms p\u00e5 v\u00e6rdierne f\u00f8r behandling\n  take(3)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/dbb690d6fea6c43c1f0a2bdabea57934.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2014 takeWhile<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/120d9fe6ddf5a60ddffc8742989b27ff.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Udsender v\u00e6rdier, s\u00e5 l\u00e6nge takeWhile ikke returnerer false, hvorefter den afmelder sig fra str\u00f8mmen.<\/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  \/\/ Udsender v\u00e6rdi hvert 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=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/d2910d1bf9fab228acc9241fdbad3d4a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2014 combineLatest<\/strong><\/p>\n<p><\/p>\n<p>Den kombinerede operator combineLatest ligner promise.all. Den kombinerer flere str\u00f8mme til \u00e9n. N\u00e5r hver str\u00f8m har sendt mindst \u00e9n v\u00e6rdi, modtager vi de seneste v\u00e6rdier fra hver str\u00f8m i en array. Derefter, efter enhver emit fra de kombinerede str\u00f8mme, vil den returnere nye v\u00e6rdier.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (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  \/\/ Udsender v\u00e6rdi hvert 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  \/\/ Udsender v\u00e6rdi hvert 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=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/7fc35461f446987ef81302ff7c2ed5a8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2014 zip<\/strong><\/p>\n<p><\/p>\n<p>Zip venter p\u00e5 en v\u00e6rdi fra hver str\u00f8m og danner en array baseret p\u00e5 disse v\u00e6rdier. Hvis der ikke kommer en v\u00e6rdi fra en af str\u00f8mmen, vil gruppen ikke blive dannet.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (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  \/\/ Udsender v\u00e6rdi hvert 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  \/\/ Udsender v\u00e6rdi hvert 750ms\n  setInterval(() =&gt; {\n    observer.next('b: ' + i++);\n  }, 750);\n});\n\nconst observer_3 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Udsender v\u00e6rdi hvert 500ms\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=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/e2606bf8ea5f8a660699ebe896a27d80.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2014 forkJoin<\/strong><\/p>\n<p><\/p>\n<p>forkJoin kombinerer ogs\u00e5 str\u00f8mme, men den udsender v\u00e6rdi kun n\u00e5r alle str\u00f8mme er afsluttet (complete).<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (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  \/\/ Udsender v\u00e6rdi hvert 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  \/\/ Udsender v\u00e6rdi hvert 750ms\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  \/\/ Udsender v\u00e6rdi hvert 500ms\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=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/df110efc7ece46fc1d8da2d7693f75bb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2014 map<\/strong><\/p>\n<p><\/p>\n<p>Transformationsoperatoren map konverterer den udsendte v\u00e6rdi til en ny. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (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  \/\/ Udsender v\u00e6rdi hvert 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=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/4e4ff3e2eb4acf69f16559c711a2e666.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operat\u00f8rer \u2013 share, tap<\/strong><\/p>\n<p><\/p>\n<p>Tap-operat\u00f8ren tillader sideeffekter, det vil sige handlinger, der ikke p\u00e5virker sekvensen.<\/p>\n<p><\/p>\n<p>Utility-operatoren share kan g\u00f8re en kold str\u00f8m varm. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynkront programmering i JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c46e96420ed78d197ceef829ff74c82d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Vi er f\u00e6rdige med operatorerne. Lad os g\u00e5 videre til Subject.<\/p>\n<p>\n<b class=\"spoiler_title\">Tankerne h\u00f8jt<\/b><\/p>\n<p>Og s\u00e5 gik jeg for at drikke noget te. Disse eksempler har tr\u00e6ttet mig \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">Familien af subjects<\/h2>\n<p><\/p>\n<p>Familien af subjects er et klart eksempel p\u00e5 varme str\u00f8mme. Disse klasser er en form for hybrid, der fungerer som b\u00e5de observable og observer. Da subject er en varm str\u00f8m, skal man tilmelde sig det. De grundl\u00e6ggende metoder er:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 sender nye data til str\u00f8mmen<\/li>\n<li>error \u2013 fejl og afslutning af str\u00f8mmen<\/li>\n<li>complete \u2013 afslutning af str\u00f8mmen<\/li>\n<li>subscribe \u2013 tilmeld dig str\u00f8mmen<\/li>\n<li>unsubscribe \u2013 afmeld dig str\u00f8mmen<\/li>\n<li>asObservable \u2013 transformer til observer<\/li>\n<li>toPromise \u2013 transformer til et l\u00f8fte<\/li>\n<\/ul>\n<p><\/p>\n<p>Der skelnes mellem 4 til 5 typer subjects. <\/p>\n<p>\n<b class=\"spoiler_title\">Tankerne h\u00f8jt<\/b><\/p>\n<p>Jeg sagde 4 p\u00e5 streamen, men det viste sig, at de havde tilf\u00f8jet endnu en. Som man siger, lever og l\u00e6r.<\/p>\n<p><\/p>\n<p>Simpel Subject <code>new Subject()<\/code>\u2013 den enkleste type af subjects. Oprettes uden parametre. Sender v\u00e6rdier, der kun kommer efter tilmelding.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject(defaultData)<\/code> \u2013 efter min mening den mest udbredte type of subjects. Tager en standardv\u00e6rdi som input. Bevarer altid data fra den seneste emission, som den sender ved tilmelding. Denne klasse har ogs\u00e5 en nyttig metode value, som returnerer den nuv\u00e6rende v\u00e6rdi i str\u00f8mmen.<\/p>\n<p><\/p>\n<p>ReplaySubject <code>new ReplaySubject(bufferSize?: number, windowTime?: number)<\/code> \u2014 Kan tage st\u00f8rrelsen af bufferet som f\u00f8rste argument og tiden, hvor vi har brug for \u00e6ndringer, som det andet.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> \u2014 ved tilmelding sker der ikke noget, og v\u00e6rdien returneres f\u00f8rst ved complete. Kun den seneste v\u00e6rdi fra str\u00f8mmen vil blive returneret.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig | Observable, destination?: Observer)<\/code> \u2014 om det er dokumentationen stille, og jeg ser det for f\u00f8rste gang selv. Hvis nogen ved, hvad det g\u00f8r, skriv, s\u00e5 tilf\u00f8jer vi det.<\/p>\n<p><\/p>\n<p>Puh. S\u00e5 har vi d\u00e6kket det hele, jeg \u00f8nskede at tale om i dag. Jeg h\u00e5ber, denne information har v\u00e6ret nyttig. Du kan selv se litteraturlisten under fanen nyttig information.<\/p>\n<p><\/p>\n<h2 id=\"poleznaya-informaciya\">Nyttig information<\/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 til streamen<\/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 Hvordan JS fungerer: en oversigt over motoren, runtime-mekanismer, opkaldsstakken<\/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 Hvordan fungerer JS: begivenhedscyklussen, asynkronitet og fem m\u00e5der at forbedre koden med 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 Hvordan fungerer Event Loop i JavaScript<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/tproger.ru\/translations\/asynchronous-javascript\/\">https:\/\/tproger.ru\/translations\/asynchronous-javascript\/<\/a><\/noindex> \u2014 Evolutionen af asynkron JavaScript<\/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 Hvad er RxJS, og hvorfor er det nyttigt at kende til<\/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 Praktisk anvendelse af 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 Oprettelse &amp; Abonnering p\u00e5 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: Hot og Cold Observables<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FiPgB\">https:\/\/clck.ru\/FiPgB<\/a><\/noindex> \u2014 Klasser, funktioner til oprettelse af Observable. Operatorer.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.learnrxjs.io\/operators\/\">https:\/\/www.learnrxjs.io\/operators\/<\/a><\/noindex> \u2014 RxJS Operatorer med eksempel<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/rxjs.dev\/api\">https:\/\/rxjs.dev\/api<\/a><\/noindex> \u2014 API-liste<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FkS8Y\">https:\/\/clck.ru\/FkS8Y<\/a><\/noindex> \u2014 Typer af Subject og Planer i RxJS<\/li>\n<\/ul>\n<p>Kilde: <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.3 - 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\/da\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"da_DK\" \/>\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\/da\/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\udd47Asynkron programmering i JavaScript. (Callback, Promise, RxJs) | ProHoster","description":"Hej alle sammen. Det er Omelnitsky Sergey her. For nylig havde jeg en stream om reaktiv programmering, hvor jeg talte om asynkronitet i JavaScript. I dag vil jeg gerne opsummere dette materiale.","canonical_url":"https:\/\/prohoster.info\/da\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"da_DK","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\/da\/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\/da\/wp-json\/wp\/v2\/posts\/36774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/comments?post=36774"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/posts\/36774\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media\/27545"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/media?parent=36774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/categories?post=36774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/da\/wp-json\/wp\/v2\/tags?post=36774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}