{"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\/de\/blog\/novosti-interneta\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","title":{"rendered":"Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Hallo zusammen. Hier ist Sergey Omelnitsky. K\u00fcrzlich habe ich einen Stream \u00fcber reaktive Programmierung gehalten, in dem ich \u00fcber Asynchronit\u00e4t in JavaScript sprach. Heute m\u00f6chte ich diese Inhalte zusammenfassen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/11acf6af8328d3deb6f0ce48e813efb7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Bevor wir mit dem Hauptmaterial beginnen, m\u00fcssen wir eine Einf\u00fchrung geben. Lassen Sie uns also mit den Definitionen beginnen: Was sind Stack und Queue?<br \/>\n<strong>Stack <\/strong>ist eine Sammlung, deren Elemente nach dem Prinzip 'Last In, First Out' (LIFO) abgerufen werden.<br \/>\n<strong>Queue <\/strong>ist eine Sammlung, deren Elemente nach dem Prinzip 'First In, First Out' (FIFO) abgerufen werden.<\/p>\n<p><\/p>\n<p>In Ordnung, fahren wir fort. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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 ist eine einstr\u00e4ngige Programmiersprache. Das bedeutet, dass es nur einen Ausf\u00fchrungsstrang und einen Stack gibt, in den Funktionen zur Ausf\u00fchrung eingereiht werden. Das hei\u00dft, zur gleichen Zeit kann JavaScript nur eine Operation ausf\u00fchren, w\u00e4hrend andere Operationen in der Warteschlange im Stack warten, bis sie aufgerufen werden. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Call Stack<\/strong> \u2014 ist eine Datenstruktur, die vereinfacht gesagt Informationen \u00fcber den Ort im Programm speichert, an dem wir uns befinden. Wenn wir in eine Funktion wechseln, f\u00fcgen wir einen Eintrag \u00fcber diese Funktion oben auf dem Stack hinzu. Wenn wir aus der Funktion zur\u00fcckkehren, ziehen wir das oberste Element vom Stack und landen dort, wo wir diese Funktion aufgerufen haben. Das ist alles, was der Stack kann. Aber jetzt stellt sich eine \u00e4u\u00dferst interessante Frage: Wie funktioniert die Asynchronit\u00e4t in JavaScript?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a29fd1dd3de06fb203c7dd14bda30548.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Tats\u00e4chlich gibt es neben dem Stack im Browser eine spezielle Warteschlange f\u00fcr die Arbeit mit dem sogenannten WebAPI. Die Funktionen aus dieser Warteschlange werden der Reihe nach erst dann ausgef\u00fchrt, wenn der Stack vollst\u00e4ndig geleert ist. Erst danach gelangen sie aus der Warteschlange auf den Stack zur Ausf\u00fchrung. Wenn sich im Stack derzeit auch nur ein Element befindet, k\u00f6nnen sie nicht auf den Stack gelangen. Genau aus diesem Grund ist der Aufruf von Funktionen per Timeout oft zeitlich ungenau, da die Funktion nicht aus der Warteschlange auf den Stack gelangen kann, solange dieser gef\u00fcllt ist. <\/p>\n<p><\/p>\n<p>Betrachten wir das folgende Beispiel und besch\u00e4ftigen wir uns mit seiner schrittweisen \"Ausf\u00fchrung\". Au\u00dferdem schauen wir uns an, was dabei im System passiert.<\/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=\"Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/379423fca95fb28b2124be03dfd15739.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>1) Zun\u00e4chst passiert nichts. Die Konsole des Browsers ist leer, der Aufruf-Stack ist leer.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Dann wird der Befehl console.log(\u2018Hi\u2019) dem Aufrufstack hinzugef\u00fcgt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Und er wird ausgef\u00fchrt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Anschlie\u00dfend wird console.log(\u2018Hi\u2019) aus dem Aufrufstack entfernt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Jetzt kommen wir zum Befehl setTimeout(function cb1() {\u2026 }). Dieser wird zum Aufruf-Stack hinzugef\u00fcgt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Der Befehl setTimeout(function cb1() {\u2026 }) wird ausgef\u00fchrt. Der Browser erstellt einen Timer, der Teil der Web-API ist. Er beginnt mit dem Countdown.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Der Befehl setTimeout(function cb1() {\u2026 }) hat seine Arbeit beendet und wird aus dem Aufruf-Stack entfernt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Der Befehl console.log(\u2018Bye\u2019) wird dem Aufrufstack hinzugef\u00fcgt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Der Befehl console.log(\u2018Bye\u2019) wird ausgef\u00fchrt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Der Befehl console.log(\u2018Bye\u2019) wird aus dem Aufrufstack entfernt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Nachdem mindestens 5000 ms vergangen sind, beendet der Timer seine Arbeit und legt das Callback cb1 in die Callback-Warteschlange.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Die Ereignisschleife nimmt die Funktion cb1 aus der Callback-Warteschlange und f\u00fcgt sie dem Aufruf-Stack hinzu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Die Funktion cb1 wird ausgef\u00fchrt und f\u00fcgt console.log(\u2018cb1\u2019) dem Aufrufstack hinzu.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Der Befehl console.log(\u2018cb1\u2019) wird ausgef\u00fchrt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Der Befehl console.log(\u2018cb1\u2019) wird aus dem Aufrufstack entfernt.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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) Die Funktion cb1 wird aus dem Aufruf-Stack entfernt.<\/p>\n<p><\/p>\n<p>Lassen Sie uns ein Beispiel in Aktion betrachten:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/3836d9df513afee374f498720990e39f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>So, nun haben wir gesehen, wie Asynchronit\u00e4t in JavaScript umgesetzt wird. Lassen Sie uns nun kurz \u00fcber die Evolution des asynchronen Codes sprechen.<\/p>\n<p><\/p>\n<h2 id=\"evolyuciya-asinhronnogo-koda\">Evolution des asynchronen Codes.<\/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>Asynchrones Programmieren, wie wir es in JavaScript kennen, kann nur mit Funktionen umgesetzt werden. Diese k\u00f6nnen wie jede andere Variable an andere Funktionen \u00fcbergeben werden. So entstanden die Callbacks. Das ist spannend und macht Spa\u00df, bis es sich in Traurigkeit und Frustration verwandelt. Warum? Weil:<\/p>\n<p><\/p>\n<ul>\n<li>Mit dem Anstieg der Komplexit\u00e4t des Codes verwandelt sich das Projekt schnell in schwer verst\u00e4ndliche, mehrfach verschachtelte Bl\u00f6cke - die sogenannte \"Callback-H\u00f6lle\".<\/li>\n<li>Fehlerbehandlung kann leicht \u00fcbersehen werden.<\/li>\n<li>Ausdr\u00fccke k\u00f6nnen nicht mit return zur\u00fcckgegeben werden.<\/li>\n<\/ul>\n<p><\/p>\n<p>Mit dem Aufkommen von Promises wurde die Situation etwas besser.<\/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('Fehler: ', e);\n});<\/code><\/pre>\n<p><\/p>\n<ul>\n<li>Mit der Einf\u00fchrung von Promise-Ketten wurde die Lesbarkeit des Codes verbessert.<\/li>\n<li>Es gibt jetzt eine separate Methode zur Fehlerbehandlung.<\/li>\n<li>Die M\u00f6glichkeit zur parallelen Ausf\u00fchrung mit Promise.all wurde hinzugef\u00fcgt.<\/li>\n<li>Verschachtelte Asynchronit\u00e4t k\u00f6nnen wir mit async\/await l\u00f6sen.<\/li>\n<\/ul>\n<p><\/p>\n<p>Promises haben jedoch ihre Einschr\u00e4nkungen. Zum Beispiel kann ein Promise ohne zus\u00e4tzliche Ma\u00dfnahmen nicht abgebrochen werden, und was am wichtigsten ist \u2013 er arbeitet mit einem einzigen Wert.<\/p>\n<p><\/p>\n<p>Jetzt sind wir sanft zum reaktiven Programmieren \u00fcbergegangen. M\u00fcde? Zum Gl\u00fcck kann man sich einen Tee machen, nachdenken und dann weiterlesen. Ich mache unterdessen weiter.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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>Reaktives Programmieren<\/strong>\u200a\u2014\u200aist eine Programmierparadigma, die auf Datenstr\u00f6men und der Verbreitung von \u00c4nderungen basiert. Lassen Sie uns genauer betrachten, was ein Datenstrom ist.<\/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>Stellen wir uns vor, wir haben ein Eingabefeld. Wir erstellen ein Array, und bei jedem Keyup-Event des Inputs speichern wir das Ereignis in unserem Array. Es ist wichtig zu beachten, dass unser Array nach Zeit sortiert ist \u2013 d.h. der Index sp\u00e4terer Ereignisse gr\u00f6\u00dfer ist als der Index fr\u00fcherer Ereignisse. Ein solches Array stellt ein vereinfachtes Modell eines Datenstroms dar, aber es ist noch kein echter Strom. Um dieses Array sicher als Strom zu bezeichnen, muss es in der Lage sein, den Abonnenten irgendwie mitzuteilen, dass neue Daten eingegangen sind. So sind wir zur Definition eines Stroms gelangt.<\/p>\n<p><\/p>\n<h3 id=\"potok-dannyh\">Datenstrom<\/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=\"Asynchrone Programmierung in 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>Strom<\/strong>\u2014 ist ein Array von zeitlich sortierten Daten, das dar\u00fcber informieren kann, dass sich die Daten ge\u00e4ndert haben. Stellen Sie sich vor, wie praktisch es wird, Code zu schreiben, bei dem eine Aktion mehrere Ereignisse an verschiedenen Stellen im Code ausl\u00f6sen muss. Wir abonnieren einfach den Strom, und er informiert uns selbst, wenn \u00c4nderungen auftreten. Und das kann die Bibliothek RxJs.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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 ist eine Bibliothek zur Arbeit mit asynchronen und ereignisgesteuerten Programmen unter Verwendung beobachtbarer Sequenzen. Die Bibliothek bietet den Haupttyp <em>Observable<\/em>, mehrere Hilfstypen (<em>Observer, Schedulers, Subjects<\/em>) und Operatoren zur Verarbeitung von Ereignissen wie Sammlungen (<em>map, filter, reduce, every<\/em> und \u00e4hnliche aus dem JavaScript Array).<\/p>\n<p><\/p>\n<p>Lassen Sie uns die grundlegenden Konzepte dieser Bibliothek genauer betrachten.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable ist der erste grundlegende Typ, den wir betrachten werden. Diese Klasse enth\u00e4lt den Hauptteil der Implementierung von RxJs. Sie ist mit dem beobachtbaren Strom verbunden, auf den man sich mit der Methode subscribe abonnieren kann.<\/p>\n<p><\/p>\n<p>In Observable wird ein Hilfsmechanismus zur Erstellung von Updates implementiert, der so genannte <em>Observer<\/em>. Die Quelle der Werte f\u00fcr den Observer wird als <em>Producer<\/em>bezeichnet. Dies kann ein Array, ein Iterator, ein Websocket, ein Ereignis usw. sein. Man kann also sagen, dass Observable ein Vermittler zwischen Producer und Observer ist. <\/p>\n<p><\/p>\n<p>Observable verarbeitet drei Arten von Ereignissen des Observers:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 neue Daten<\/li>\n<li>error \u2013 einen Fehler, wenn die Sequenz aufgrund einer Ausnahme beendet wurde. Dieses Ereignis impliziert ebenfalls das Ende der Sequenz.<\/li>\n<li>complete \u2014 Signal f\u00fcr den Abschluss der Sequenz. Dies bedeutet, dass keine neuen Daten mehr kommen werden.<\/li>\n<\/ul>\n<p><\/p>\n<p>Lass uns eine Demo anschauen:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c5bcd2af0f18b6de3ab0dbc20db595d1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Zu Beginn werden wir die Werte 1, 2, 3 verarbeiten, und nach 1 Sekunde erhalten wir 4 und beenden unseren Stream.<\/p>\n<p>\n<b class=\"spoiler_title\">Gedanken laut<\/b><\/p>\n<p>Und da wurde mir klar, dass es interessanter war, dar\u00fcber zu erz\u00e4hlen, als es aufzuschreiben. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Abonnement<\/h3>\n<p><\/p>\n<p>Wenn wir ein Abonnement f\u00fcr den Stream erstellen, legen wir eine neue Klasse an <strong>subscription<\/strong>, die uns die M\u00f6glichkeit gibt, das Abonnement \u00fcber die Methode <em>unsubscribe<\/em>zu k\u00fcndigen. Au\u00dferdem k\u00f6nnen wir Abonnements mit der Methode <em>add<\/em>gruppieren. Und es ist logisch, dass wir Streams mit <em>remove<\/em>entgruppieren k\u00f6nnen. Die Methoden add und remove akzeptieren eine andere Subscription als Eingabe. Ich m\u00f6chte erw\u00e4hnen, dass wenn wir uns abmelden, wir uns auch von allen untergeordneten Abonnements abmelden, als ob wir deren Methode unsubscribe aufgerufen h\u00e4tten. Machen wir weiter.<\/p>\n<p><\/p>\n<h3 id=\"vidy-potokov\">Arten von Streams<\/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>Der Producer wird au\u00dferhalb des Observable erstellt.<\/td>\n<td>Der Producer wird innerhalb des Observable erstellt.<\/td>\n<\/tr>\n<tr>\n<td>Daten werden beim Erstellen des Observable \u00fcbergeben.<\/td>\n<td>Daten werden beim Abonnieren mitgeteilt.<\/td>\n<\/tr>\n<tr>\n<td>Zus\u00e4tzliche Logik f\u00fcr die Abmeldung ist erforderlich.<\/td>\n<td>Der Stream endet selbstst\u00e4ndig.<\/td>\n<\/tr>\n<tr>\n<td>Verwendet eine Eins-zu-Viele-Beziehung.<\/td>\n<td>Verwendet eine Eins-zu-Eins-Beziehung.<\/td>\n<\/tr>\n<tr>\n<td>Alle Abonnements haben einen einheitlichen Wert.<\/td>\n<td>Die Abonnements sind unabh\u00e4ngig<\/td>\n<\/tr>\n<tr>\n<td>Daten k\u00f6nnen verloren gehen, wenn kein Abonnement besteht<\/td>\n<td>Alle Werte des Streams werden f\u00fcr das neue Abonnement neu ausgegeben<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Um eine Analogie zu ziehen, w\u00fcrde ich den hei\u00dfen Stream mit einem Film im Kino vergleichen. Ab dem Zeitpunkt, an dem du angekommen bist, beginnst du mit dem Anschauen. Den kalten Stream w\u00fcrde ich mit einem Anruf beim technischen Support vergleichen. Jeder Anrufer h\u00f6rt sich die Ansage des Anrufbeantworters von Anfang bis Ende an, aber du kannst auflegen, indem du dich abmeldest.<\/p>\n<p><\/p>\n<p>Ich m\u00f6chte darauf hinweisen, dass es auch die sogenannten warmen Streams gibt (eine solche Bezeichnung habe ich sehr selten gesehen und nur in ausl\u00e4ndischen Communities) \u2013 das ist ein Stream, der sich von einem kalten Stream in einen hei\u00dfen verwandelt. Die Frage ist \u2013 wo verwendet man das?)) Ich werde ein praktisches Beispiel anf\u00fchren.<\/p>\n<p><\/p>\n<p>Ich arbeite mit Angular. Es nutzt aktiv RxJS. F\u00fcr den Datenabruf vom Server erwarte ich einen kalten Stream und verwende diesen Stream im Template mit Hilfe des asyncPipe. Wenn ich diesen Pipe mehrfach verwende, wird jeder Pipe, zur\u00fcckkommend auf die Definition des kalten Streams, die Daten vom Server anfordern, was, milde gesagt, seltsam ist. Wenn ich jedoch den kalten Stream in einen warmen Stream umwandle, erfolgt die Anfrage nur einmal.<\/p>\n<p><\/p>\n<p>Insgesamt ist das Verst\u00e4ndnis der verschiedenen Stream-Arten f\u00fcr Anf\u00e4nger ziemlich herausfordernd, aber wichtig. <\/p>\n<p><\/p>\n<h3 id=\"operators\">Operatoren<\/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>Die Erweiterung der M\u00f6glichkeiten zur Arbeit mit Streams bieten uns Operatoren. Sie helfen, die Ereignisse, die in Observable ablaufen, zu steuern. Wir werden ein paar der beliebtesten betrachten. Detailliertere Informationen zu Operatoren finden Sie in den Links zur n\u00fctzlichen Information.<\/p>\n<p><\/p>\n<p><strong>Operatoren \u2014 of<\/strong><\/p>\n<p><\/p>\n<p>Lassen Sie uns mit dem Hilfsoperator of beginnen. Er erstellt ein Observable basierend auf einem einfachen Wert.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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>Operatoren \u2014 filter<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/24ac65fdb5ccc7f6301b3dfe49f1e804.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Der Filteroperator filter, wie der Name schon sagt, filtert das Signal des Streams. Wenn der Operator wahr zur\u00fcckgibt, wird es weitergeleitet.<\/p>\n<p><\/p>\n<p><strong>Operatoren \u2014 take<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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 Gibt die Anzahl der Emissionen an, nach der der Stream beendet wird.<\/p>\n<p><\/p>\n<p><strong>Operatoren \u2014 debounceTime<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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 verwirft Emissionen, die im angegebenen Zeitintervall zwischen den Ausgaben liegen \u2014 gibt nach Ablauf des Zeitintervalls den letzten Wert aus.<\/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  \/\/ Gibt alle 1000 ms einen Wert aus\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n\n  \/\/ Gibt alle 1500 ms einen Wert aus\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1500);\n}).pipe(\n  debounceTime(700),  \/\/ Wartet 700 ms auf Werte, bevor sie verarbeitet werden\n  take(3)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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>Operatoren \u2014 takeWhile<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/120d9fe6ddf5a60ddffc8742989b27ff.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Gibt Werte aus, solange takeWhile nicht false zur\u00fcckgibt, danach wird vom Stream abgemeldet.<\/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  \/\/ Gibt alle 1000 ms einen Wert aus\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=\"Asynchrone Programmierung in 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>Operatoren \u2014 combineLatest<\/strong><\/p>\n<p><\/p>\n<p>Der kombinierte Operator combineLatest \u00e4hnelt etwas dem promise.all. Er vereint mehrere Streams in einen einzigen. Nachdem jeder Stream mindestens einen Emit erzeugt hat, erhalten wir die letzten Werte von jedem in Form eines Arrays. Danach, nach einem beliebigen Emit aus den kombinierten Streams, gibt er neue Werte zur\u00fcck.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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  \/\/ Emitte einen Wert alle 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  \/\/ Emitte einen Wert alle 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=\"Asynchrone Programmierung in 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>Operatoren \u2014 zip<\/strong><\/p>\n<p><\/p>\n<p>Zip \u2014 wartet auf einen Wert aus jedem Stream und bildet ein Array basierend auf diesen Werten. Wenn aus einem Stream kein Wert kommt, wird die Gruppe nicht gebildet.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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  \/\/ 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\nconst observer_3 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 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=\"Asynchrone Programmierung in 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>Operators \u2014 forkJoin<\/strong><\/p>\n<p><\/p>\n<p>forkJoin kombiniert ebenfalls Streams, gibt jedoch erst dann einen Wert aus, wenn alle Streams abgeschlossen sind (complete).<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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  \/\/ Emit value every 1000ms\n  setInterval(() =&gt; {\n    observer.next('a: ' + i++);\n  }, 1000);\n}).pipe(take(3));\n\nconst observer_2 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emit value every 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  \/\/ Emit value every 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=\"Asynchrone Programmierung in 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>Operators \u2014 map<\/strong><\/p>\n<p><\/p>\n<p>Der Transformationsoperator map wandelt den Wert des Emit in einen neuen um. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in 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  \/\/ Gibt alle 1000 ms einen Wert aus\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=\"Asynchrone Programmierung in 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>Operatoren \u2013 share, tap<\/strong><\/p>\n<p><\/p>\n<p>Der Operator tap \u2013 erm\u00f6glicht side effects, also Handlungen, die die Reihenfolge nicht beeinflussen.<\/p>\n<p><\/p>\n<p>Der Utility-Operator share verwandelt einen kalten Stream in einen hei\u00dfen. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c46e96420ed78d197ceef829ff74c82d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Wir sind mit den Operatoren fertig. Kommen wir zum Subject.<\/p>\n<p>\n<b class=\"spoiler_title\">Gedanken laut<\/b><\/p>\n<p>Und hier habe ich eine Teepause gemacht. Diese Beispiele haben mich ersch\u00f6pft \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">Familie der Subjects<\/h2>\n<p><\/p>\n<p>Die Familie der Subjects ist ein eindrucksvolles Beispiel f\u00fcr hei\u00dfe Streams. Diese Klassen sind eine Art Hybrid, der sowohl als Observable als auch als Observer fungiert. Da Subject ein hei\u00dfer Stream ist, muss man sich davon abmelden. Zu den Hauptmethoden geh\u00f6ren:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 \u00fcbertr\u00e4gt neue Daten in den Stream<\/li>\n<li>error \u2013 Fehler und Beendigung des Streams<\/li>\n<li>complete \u2013 Beendigung des Streams<\/li>\n<li>subscribe \u2013 sich f\u00fcr den Stream anmelden<\/li>\n<li>unsubscribe \u2013 sich vom Stream abmelden<\/li>\n<li>asObservable \u2013 in einen Beobachter umwandeln<\/li>\n<li>toPromise \u2013 in ein Promise umwandeln<\/li>\n<\/ul>\n<p><\/p>\n<p>Es gibt 4 bis 5 Typen von Subjects. <\/p>\n<p>\n<b class=\"spoiler_title\">Gedanken laut<\/b><\/p>\n<p>Im Stream sprach ich von 4, aber es scheint, dass sie noch einen hinzugef\u00fcgt haben. Wie man sagt: Ein Leben lang lernen.<\/p>\n<p><\/p>\n<p>Einfaches Subject <code>new Subject()<\/code>\u2013 die einfachste Art von Subjects. Wird ohne Parameter erstellt. \u00dcbertr\u00e4gt Werte, die nur nach der Subscription empfangen werden.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject( defaultData )<\/code> \u2013 meiner Meinung nach die h\u00e4ufigste Art von Subjects. Nimmt einen Standardwert als Eingabe entgegen. Speichert immer die Daten des letzten Emits, die bei der Subscription \u00fcbermittelt werden. Diese Klasse hat au\u00dferdem eine n\u00fctzliche Methode value, die den aktuellen Wert des Streams zur\u00fcckgibt.<\/p>\n<p><\/p>\n<p>ReplaySubject <code>new ReplaySubject(bufferSize?: number, windowTime?: number)<\/code> \u2014 Optional kann sie beim ersten Argument die Gr\u00f6\u00dfe des Pufferwerts annehmen, den sie speichern soll, und beim zweiten das Zeitfenster, in dem wir die \u00c4nderungen ben\u00f6tigen.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> \u2014 Bei der Subscription passiert nichts und der Wert wird nur bei complete zur\u00fcckgegeben. Nur der letzte Wert des Streams wird zur\u00fcckgegeben.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig | Observable, destination?: Observer)<\/code> \u2014 Die Dokumentation schweigt dar\u00fcber und ich sehe es selbst zum ersten Mal. Wer wei\u00df, was es macht, schreibt bitte, wir erg\u00e4nzen.<\/p>\n<p><\/p>\n<p>So, das war alles, was ich heute besprechen wollte. Ich hoffe, die Informationen waren n\u00fctzlich. Sie k\u00f6nnen die Literaturliste selbst im Tab \"N\u00fctzliche Informationen\" einsehen.<\/p>\n<p><\/p>\n<h2 id=\"poleznaya-informaciya\">N\u00fctzliche Informationen<\/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 zum 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 Wie JS funktioniert: \u00dcberblick \u00fcber die Engine, Ausf\u00fchrungsmechanismen, Stack<\/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 Wie JS funktioniert: Ereigniszyklus, Asynchronit\u00e4t und f\u00fcnf M\u00f6glichkeiten, den Code mit async \/ await zu verbessern<\/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 Wie die Event Loop in JavaScript funktioniert<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/tproger.ru\/translations\/asynchronous-javascript\/\">https:\/\/tproger.ru\/translations\/asynchronous-javascript\/<\/a><\/noindex> \u2014 Die Evolution von asynchronem 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 Was ist RxJS und warum ist es wichtig?<\/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 Praktische Anwendung von 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 Erstellen &amp; Abonnieren von 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: Hei\u00dfe und kalte Observables<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FiPgB\">https:\/\/clck.ru\/FiPgB<\/a><\/noindex> \u2014 Klassen und Funktionen zur Erstellung von Observable. Operatoren.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.learnrxjs.io\/operators\/\">https:\/\/www.learnrxjs.io\/operators\/<\/a><\/noindex> \u2014 RxJS Operatoren anhand von Beispielen<\/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 Arten von Subject und Scheduling in RxJS<\/li>\n<\/ul>\n<p>Quelle: <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-novosti-interneta"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - 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. \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\" \/>\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\/de\/blog\/novosti-interneta\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"de_DE\" \/>\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. \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\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/de\/blog\/novosti-interneta\/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\udd47Asynchrone Programmierung in JavaScript. (Callback, Promise, RxJs) | ProHoster","description":"Hallo zusammen. Hier ist Sergey Omelnitsky. Vor nicht allzu langer Zeit habe ich einen Stream \u00fcber reaktive Programmierung gehalten, in dem ich \u00fcber Asynchronit\u00e4t in JavaScript gesprochen habe. Heute m\u00f6chte ich dieses Material zusammenfassen. Aber bevor wir mit dem eigentlichen Material beginnen, m\u00fcssen wir eine Einf\u00fchrung machen. Lassen Sie uns also mit den Definitionen starten: Was sind Stack und Warteschlange? Ein Stack ist eine Sammlung, deren Elemente","canonical_url":"https:\/\/prohoster.info\/de\/blog\/novosti-interneta\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"de_DE","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. \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","og:url":"https:\/\/prohoster.info\/de\/blog\/novosti-interneta\/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":null,"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-01-22 04:48:19"},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/36774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/comments?post=36774"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/posts\/36774\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media\/27545"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/media?parent=36774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/categories?post=36774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/de\/wp-json\/wp\/v2\/tags?post=36774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}