{"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\/fr\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","title":{"rendered":"Programmation asynchrone en JavaScript. (Callback, Promise, RxJs)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Bonjour \u00e0 tous. Ici, Sergey Omelnitsky. Il n'y a pas si longtemps, j'ai anim\u00e9 un stream sur la programmation r\u00e9active, o\u00f9 j'ai parl\u00e9 de l'asynchrone en JavaScript. Aujourd'hui, je voudrais r\u00e9sumer ce mat\u00e9riel. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/11acf6af8328d3deb6f0ce48e813efb7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mais avant de commencer le contenu principal, nous devons faire une introduction. Alors, commen\u00e7ons par les d\u00e9finitions : qu'est-ce qu'une pile et une file d'attente ?<br \/>\n<strong>Pile <\/strong>\u2014 c'est une collection dont les \u00e9l\u00e9ments sont obtenus selon le principe \u00ab dernier entr\u00e9, premier sorti \u00bb LIFO.<br \/>\n<strong>File d'attente <\/strong>\u2014 c'est une collection dont les \u00e9l\u00e9ments sont re\u00e7us selon le principe \u00ab premier entr\u00e9, premier sorti \u00bb FIFO.<\/p>\n<p><\/p>\n<p>D'accord, continuons. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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 est un langage de programmation \u00e0 thread unique. Cela signifie qu'il n'y a qu'un seul fil d'ex\u00e9cution et une seule pile, dans laquelle les fonctions sont plac\u00e9es en attente d'ex\u00e9cution. Par cons\u00e9quent, \u00e0 un moment donn\u00e9, JavaScript ne peut ex\u00e9cuter qu'une seule op\u00e9ration, les autres op\u00e9rations attendant leur tour dans la pile jusqu'\u00e0 ce qu'elles soient appel\u00e9es. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Pile d'appels<\/strong> \u2014 c'est une structure de donn\u00e9es qui, en termes simples, enregistre des informations sur l'endroit o\u00f9 nous en sommes dans le programme. Lorsque nous entrons dans une fonction, nous ajoutons un enregistrement \u00e0 son sujet en haut de la pile. Lorsque nous revenons de la fonction, nous retirons l'\u00e9l\u00e9ment du haut de la pile et nous nous retrouvons l\u00e0 d'o\u00f9 nous avons appel\u00e9 cette fonction. C'est tout ce que fait la pile. Et maintenant, une question tr\u00e8s int\u00e9ressante. Comment l'asynchrone fonctionne-t-il alors en JavaScript ?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a29fd1dd3de06fb203c7dd14bda30548.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En r\u00e9alit\u00e9, en plus de la pile, il y a dans les navigateurs une file d'attente sp\u00e9ciale pour travailler avec ce que l'on appelle le WebAPI. Les fonctions de cette file d'attente ne s'ex\u00e9cutent qu'apr\u00e8s que la pile est compl\u00e8tement nettoy\u00e9e. Ce n'est qu'apr\u00e8s cela qu'elles passent de la file d'attente \u00e0 la pile pour ex\u00e9cution. Si la pile contient au moins un \u00e9l\u00e9ment, elles ne peuvent pas entrer dans la pile. C'est exactement pour cette raison que l'appel de fonctions par timeout peut souvent ne pas \u00eatre pr\u00e9cis en termes de temps, car la fonction ne peut pas entrer de la file d'attente dans la pile tant qu'elle est pleine. <\/p>\n<p><\/p>\n<p>Consid\u00e9rons l'exemple suivant et analysons son \u00ab ex\u00e9cution \u00bb \u00e9tape par \u00e9tape. De plus, regardons ce qui se passe dans le syst\u00e8me.<\/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=\"Programmation asynchrone en 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) Rien ne se passe encore. La console du navigateur est vide, la pile d'appels est vide.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) Ensuite, la commande console.log(\u2018Hi\u2019) est ajout\u00e9e \u00e0 la pile d\u2019appels.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) Et elle s'ex\u00e9cute.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) Puis, console.log(\u2018Hi\u2019) est retir\u00e9 de la pile d\u2019appels.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) Nous passons maintenant \u00e0 la commande setTimeout(function cb1() {\u2026 }). Elle est ajout\u00e9e \u00e0 la pile d'appels.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La commande setTimeout(function cb1() {\u2026 }) est ex\u00e9cut\u00e9e. Le navigateur cr\u00e9e un minuteur qui fait partie de l'API Web. Il comptera \u00e0 rebours.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La commande setTimeout(function cb1() {\u2026 }) a termin\u00e9 son travail et est supprim\u00e9e de la pile d'appels.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La commande console.log(\u2018Bye\u2019) est ajout\u00e9e \u00e0 la pile d\u2019appels.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La commande console.log(\u2018Bye\u2019) est ex\u00e9cut\u00e9e.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La commande console.log(\u2018Bye\u2019) est retir\u00e9e de la pile d\u2019appels.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) Apr\u00e8s au moins 5000 ms, le minuteur termine son travail et place le callback cb1 dans la file d'attente des callbacks.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La boucle d'\u00e9v\u00e9nements prend la fonction cb1 de la file d'attente des callbacks et l'ajoute \u00e0 la pile d'appels.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La fonction cb1 est ex\u00e9cut\u00e9e et ajoute console.log(\u2018cb1\u2019) \u00e0 la pile d\u2019appels.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La commande console.log(\u2018cb1\u2019) est ex\u00e9cut\u00e9e.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La commande console.log(\u2018cb1\u2019) est retir\u00e9e de la pile d\u2019appels.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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) La fonction cb1 est supprim\u00e9e de la pile d'appels.<\/p>\n<p><\/p>\n<p>Regardons un exemple en dynamique :<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/3836d9df513afee374f498720990e39f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Eh bien, nous avons vu comment l'asynchronicit\u00e9 est impl\u00e9ment\u00e9e en JavaScript. Maintenant, discutons bri\u00e8vement de l'\u00e9volution du code asynchrone.<\/p>\n<p><\/p>\n<h2 id=\"evolyuciya-asinhronnogo-koda\">L'\u00e9volution du code asynchrone.<\/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>La programmation asynchrone telle que nous la connaissons en JavaScript ne peut \u00eatre r\u00e9alis\u00e9e qu'avec des fonctions. Celles-ci peuvent \u00eatre transmises comme n'importe quelle autre variable \u00e0 d'autres fonctions. C'est ainsi qu'ont \u00e9t\u00e9 cr\u00e9\u00e9s les callbacks. Et c'est bien, amusant et joyeux, jusqu'\u00e0 ce que cela se transforme en tristesse, m\u00e9lancolie et chagrin. Pourquoi ? C'est simple:<\/p>\n<p><\/p>\n<ul>\n<li>Avec l'augmentation de la complexit\u00e9 du code, le projet devient rapidement des blocs imbriqu\u00e9s difficiles \u00e0 comprendre \u2014 \u00abcallback hell\u00bb.<\/li>\n<li>La gestion des erreurs peut facilement \u00eatre n\u00e9glig\u00e9e.<\/li>\n<li>On ne peut pas retourner des expressions avec return.<\/li>\n<\/ul>\n<p><\/p>\n<p>Avec l'apparition de Promise, la situation est devenue un peu meilleure.<\/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('\u00c9CHEC ICI');\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('erreur: ', e);\n});<\/code><\/pre>\n<p><\/p>\n<ul>\n<li>Des cha\u00eenes de promesses sont apparues, ce qui a am\u00e9lior\u00e9 la lisibilit\u00e9 du code.<\/li>\n<li>Un m\u00e9thode distincte de gestion des erreurs est apparue.<\/li>\n<li>Il est d\u00e9sormais possible d'ex\u00e9cuter des t\u00e2ches en parall\u00e8le avec Promise.all<\/li>\n<li>Nous pouvons r\u00e9soudre l'asynchronicit\u00e9 imbriqu\u00e9e avec async\/await<\/li>\n<\/ul>\n<p><\/p>\n<p>Cependant, il y a des limitations avec les promesses. Par exemple, une promesse ne peut pas \u00eatre annul\u00e9e sans une manipulation compliqu\u00e9e, et surtout, elle ne fonctionne qu'avec une seule valeur.<\/p>\n<p><\/p>\n<p>Eh bien, nous avons tranquillement abord\u00e9 la programmation r\u00e9active. Fatigu\u00e9 ? Heureusement, vous pouvez aller pr\u00e9parer une tasse de th\u00e9, r\u00e9fl\u00e9chir et revenir lire la suite. Pendant ce temps, je vais continuer.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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>Programmation r\u00e9active<\/strong>\u200a\u2014\u200aune paradigme de programmation ax\u00e9e sur les flux de donn\u00e9es et la diffusion des modifications. Analysons plus en d\u00e9tail ce qu'est un flux de donn\u00e9es.<\/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>Imaginons que nous avons un champ de saisie. Nous cr\u00e9ons un tableau, et \u00e0 chaque \u00e9v\u00e9nement keyup de l'input, nous allons sauvegarder cet \u00e9v\u00e9nement dans notre tableau. Il est \u00e0 noter que notre tableau est tri\u00e9 par temps, c'est-\u00e0-dire que l'index des \u00e9v\u00e9nements plus r\u00e9cents est sup\u00e9rieur \u00e0 l'index des \u00e9v\u00e9nements plus anciens. Ce tableau repr\u00e9sente un mod\u00e8le simplifi\u00e9 d'un flux de donn\u00e9es, mais ce n'est pas encore un flux. Pour que ce tableau puisse \u00eatre d\u00e9sign\u00e9 comme un flux, il doit \u00eatre capable d'informer d'une mani\u00e8re ou d'une autre les abonn\u00e9s qu'il a re\u00e7u de nouvelles donn\u00e9es. Ainsi, nous sommes parvenus \u00e0 la d\u00e9finition d'un flux.<\/p>\n<p><\/p>\n<h3 id=\"potok-dannyh\">Flux de donn\u00e9es<\/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=\"Programmation asynchrone en 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>Flux\u200a<\/strong>\u200a\u2014\u200aest un tableau de donn\u00e9es, tri\u00e9 par temps, qui peut signaler que les donn\u00e9es ont chang\u00e9. Imaginez \u00e0 quel point il devient pratique d'\u00e9crire du code qui n\u00e9cessite d'appeler plusieurs \u00e9v\u00e9nements \u00e0 diff\u00e9rents endroits du code. Nous nous abonnissons simplement au flux, et il nous informera lui-m\u00eame des modifications. C'est ce que fait la biblioth\u00e8que RxJs.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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> \u200a\u2014\u200aune biblioth\u00e8que pour travailler avec des programmes asynchrones et bas\u00e9s sur des \u00e9v\u00e9nements utilisant des s\u00e9quences observables. La biblioth\u00e8que fournit le type principal <em>Observable<\/em>, plusieurs types auxiliaires (<em>Observer, Schedulers, Subjects<\/em>) et des op\u00e9rateurs pour travailler avec des \u00e9v\u00e9nements comme avec des collections (<em>map, filter, reduce, every<\/em> et similaires du tableau JavaScript).<\/p>\n<p><\/p>\n<p>Passons en revue les concepts de base de cette biblioth\u00e8que.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable \u2014 le premier type de base que nous allons examiner. Cette classe contient la majeure partie de l'impl\u00e9mentation de RxJs. Elle est li\u00e9e \u00e0 un flux observable, auquel on peut s'abonner via la m\u00e9thode subscribe.<\/p>\n<p><\/p>\n<p>Un m\u00e9canisme auxiliaire pour cr\u00e9er des mises \u00e0 jour est impl\u00e9ment\u00e9 dans Observable, appel\u00e9 <em>Observer<\/em>. La source des valeurs pour l'Observer est appel\u00e9e <em>Producteur<\/em>. Cela peut \u00eatre un tableau, un it\u00e9rateur, un web socket, un \u00e9v\u00e9nement, etc. On peut donc dire que l'observable agit comme un interm\u00e9diaire entre le Producteur et l'Observer. <\/p>\n<p><\/p>\n<p>Observable g\u00e8re trois types d'\u00e9v\u00e9nements de l'Observer :<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 nouvelles donn\u00e9es<\/li>\n<li>error \u2013 une erreur, si la s\u00e9quence se termine en raison d'une exception. Cet \u00e9v\u00e9nement implique aussi la fin de la s\u00e9quence.<\/li>\n<li>complete \u2014 un signal indiquant la fin de la s\u00e9quence. Cela signifie qu'il n'y aura plus de nouvelles donn\u00e9es.<\/li>\n<\/ul>\n<p><\/p>\n<p>Voyons une d\u00e9mo :<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c5bcd2af0f18b6de3ab0dbc20db595d1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Au d\u00e9but, nous traiterons les valeurs 1, 2, 3, puis apr\u00e8s 1 seconde, nous obtiendrons 4 et terminerons notre flux.<\/p>\n<p>\n<b class=\"spoiler_title\">R\u00e9flexion<\/b><\/p>\n<p>Et l\u00e0, j'ai r\u00e9alis\u00e9 qu'il \u00e9tait plus int\u00e9ressant de raconter que d'\u00e9crire \u00e0 ce sujet. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Subscription<\/h3>\n<p><\/p>\n<p>Lorsque nous nous abonnons \u00e0 un flux, nous cr\u00e9ons une nouvelle classe <strong>subscription<\/strong>, qui nous permet d'annuler l'abonnement gr\u00e2ce \u00e0 la m\u00e9thode <em>unsubscribe<\/em>. Nous pouvons \u00e9galement grouper les abonnements \u00e0 l'aide de la m\u00e9thode <em>add<\/em>. Il est logique que nous puissions d\u00e9groupper les flux gr\u00e2ce \u00e0 <em>remove<\/em>. Les m\u00e9thodes add et remove acceptent comme argument un autre abonnement. Il est important de noter que lorsque nous nous d\u00e9sinscrivons, cela d\u00e9sinscrit \u00e9galement tous les abonnements enfants comme si nous avions \u00e9galement appel\u00e9 la m\u00e9thode unsubscribe sur eux. Continuons.<\/p>\n<p><\/p>\n<h3 id=\"vidy-potokov\">Types de flux<\/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>Le Producteur est cr\u00e9\u00e9 \u00e0 l'ext\u00e9rieur de l'observable.<\/td>\n<td>Le Producteur est cr\u00e9\u00e9 \u00e0 l'int\u00e9rieur de l'observable.<\/td>\n<\/tr>\n<tr>\n<td>Les donn\u00e9es sont transmises au moment de la cr\u00e9ation de l'observable.<\/td>\n<td>Les donn\u00e9es sont communiqu\u00e9es au moment de l'abonnement.<\/td>\n<\/tr>\n<tr>\n<td>Une logique suppl\u00e9mentaire est n\u00e9cessaire pour la d\u00e9sinscription.<\/td>\n<td>Le flux se termine de lui-m\u00eame.<\/td>\n<\/tr>\n<tr>\n<td>Utilise une relation un-\u00e0-plusieurs.<\/td>\n<td>Utilise une relation un-\u00e0-un.<\/td>\n<\/tr>\n<tr>\n<td>Tous les abonnements partagent une valeur unique.<\/td>\n<td>Les abonnements sont ind\u00e9pendants.<\/td>\n<\/tr>\n<tr>\n<td>Les donn\u00e9es peuvent \u00eatre perdues s'il n'y a pas d'abonnement.<\/td>\n<td>Rediffuse toutes les valeurs du flux pour un nouvel abonnement.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Pour faire une analogie, je repr\u00e9senterais un flux chaud comme un film au cin\u00e9ma. Peu importe \u00e0 quel moment tu arrives, c'est \u00e0 partir de ce moment que tu commences \u00e0 regarder. Un flux froid pourrait \u00eatre compar\u00e9 \u00e0 un appel au support technique. Quiconque appelle \u00e9coute l'enregistrement du r\u00e9pondeur de bout en bout, mais tu peux raccrocher avec la m\u00e9thode unsubscribe.<\/p>\n<p><\/p>\n<p>Je voudrais souligner qu'il existe \u00e9galement ce qu'on appelle des flux chauds (une d\u00e9finition que j'ai rencontr\u00e9e tr\u00e8s rarement et uniquement dans des communaut\u00e9s \u00e9trang\u00e8res) \u2014 c'est un flux qui se transforme d'un flux froid en un flux chaud. La question se pose : o\u00f9 les utiliser ? Je vais donner un exemple pratique.<\/p>\n<p><\/p>\n<p>Je travaille avec Angular. Il utilise activement RxJS. Pour obtenir des donn\u00e9es du serveur, j'attends un flux froid et j'utilise ce flux dans le mod\u00e8le avec asyncPipe. Si j'utilise ce pipe plusieurs fois, alors, pour revenir \u00e0 la d\u00e9finition du flux froid, chaque pipe va demander des donn\u00e9es au serveur, ce qui est, pour le dire poliment, \u00e9trange. Mais si je transforme un flux froid en flux chaud, la demande se fera une seule fois.<\/p>\n<p><\/p>\n<p>En fait, la compr\u00e9hension des types de flux est assez complexe pour les d\u00e9butants, mais c'est important. <\/p>\n<p><\/p>\n<h3 id=\"operators\">Op\u00e9rateurs<\/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>Nous pouvons \u00e9tendre les possibilit\u00e9s de travail avec les flux gr\u00e2ce aux op\u00e9rateurs. Ils aident \u00e0 contr\u00f4ler les \u00e9v\u00e9nements qui se produisent dans un Observable. Nous allons examiner quelques-uns des plus populaires, et pour plus de d\u00e9tails sur les op\u00e9rateurs, vous pouvez consulter les liens dans les informations utiles.<\/p>\n<p><\/p>\n<p><strong>Op\u00e9rateurs \u2014 of<\/strong><\/p>\n<p><\/p>\n<p>Commen\u00e7ons par l'op\u00e9rateur auxiliaire of. Il cr\u00e9e un Observable \u00e0 partir d'une valeur simple.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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>Op\u00e9rateurs \u2014 filter<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/24ac65fdb5ccc7f6301b3dfe49f1e804.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>L'op\u00e9rateur de filtrage filter, comme son nom l'indique, filtre le signal du flux. Si l'op\u00e9rateur retourne vrai, il passe \u00e0 la suite.<\/p>\n<p><\/p>\n<p><strong>Op\u00e9rateurs \u2014 take<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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 Prend le nombre d'\u00e9missions apr\u00e8s lequel il termine le flux.<\/p>\n<p><\/p>\n<p><strong>Op\u00e9rateurs \u2014 debounceTime<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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 rejette les valeurs \u00e9mises qui se produisent dans un intervalle de temps sp\u00e9cifi\u00e9 entre les sorties \u2014 apr\u00e8s l'intervalle de temps \u00e9coul\u00e9, il \u00e9met la derni\u00e8re valeur.<\/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  \/\/ \u00c9met une valeur toutes les 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n\n  \/\/ \u00c9met une valeur toutes les 1500ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1500);\n}).pipe(\n  debounceTime(700),  \/\/ Attend 700ms avant de traiter la valeur\n  take(3)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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>Op\u00e9rateurs \u2014 takeWhile<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/120d9fe6ddf5a60ddffc8742989b27ff.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u00c9met des valeurs tant que takeWhile ne retourne pas false, apr\u00e8s quoi il se d\u00e9sabonne du flux.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { Observable } = Rx;\nconst { debounceTime, takeWhile } = RxOperators;\n\nObservable.create((observer) =&gt; {\n  let i = 1;\n  observer.next(i++);\n  \/\/ \u00c9met une valeur toutes les 1000 ms\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=\"Programmation asynchrone en 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>Op\u00e9rateurs \u2014 combineLatest<\/strong><\/p>\n<p><\/p>\n<p>L'op\u00e9rateur combin\u00e9 combineLatest est similaire \u00e0 promise.all. Il regroupe plusieurs flux en un seul. Une fois que chaque flux a \u00e9mis au moins une valeur, nous recevons les derni\u00e8res valeurs de chacun sous forme de tableau. Ensuite, apr\u00e8s n'importe quelle \u00e9mission des flux combin\u00e9s, il renverra de nouvelles valeurs.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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  \/\/ \u00c9met une valeur toutes les 1000 ms\n  setInterval(() =&gt; {\n    observer.next('a: ' + i++);\n  }, 1000);\n});\n\nconst observer_2 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ \u00c9met une valeur toutes les 750 ms\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=\"Programmation asynchrone en 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>Op\u00e9rateurs \u2014 zip<\/strong><\/p>\n<p><\/p>\n<p>Zip attend une valeur de chaque flux et forme un tableau bas\u00e9 sur ces valeurs. Si aucune valeur n'est re\u00e7ue d'un flux, le groupe ne sera pas form\u00e9.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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  \/\/ \u00c9met une valeur toutes les 1000 ms\n  setInterval(() =&gt; {\n    observer.next('a: ' + i++);\n  }, 1000);\n});\n\nconst observer_2 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ \u00c9met une valeur toutes les 750 ms\n  setInterval(() =&gt; {\n    observer.next('b: ' + i++);\n  }, 750);\n});\n\nconst observer_3 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ \u00c9met une valeur toutes les 500 ms\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=\"Programmation asynchrone en 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>Op\u00e9rateurs \u2014 forkJoin<\/strong><\/p>\n<p><\/p>\n<p>forkJoin regroupe \u00e9galement les flux, mais il \u00e9met une valeur uniquement lorsque tous les flux sont termin\u00e9s (compl\u00e9t\u00e9s).<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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  \/\/ \u00c9met une valeur toutes les 1000 ms\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  \/\/ \u00c9met une valeur toutes les 750 ms\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  \/\/ \u00c9met une valeur toutes les 500 ms\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=\"Programmation asynchrone en 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>Op\u00e9rateurs \u2014 map<\/strong><\/p>\n<p><\/p>\n<p>L'op\u00e9rateur de transformation map convertit la valeur \u00e9mise en une nouvelle. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en 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  \/\/ \u00c9met une valeur toutes les 1000 ms\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=\"Programmation asynchrone en 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>Op\u00e9rateurs \u2013 share, tap<\/strong><\/p>\n<p><\/p>\n<p>L'op\u00e9rateur tap \u2014 permet d'effectuer des effets secondaires, c'est-\u00e0-dire des actions qui n'influencent pas la s\u00e9quence.<\/p>\n<p><\/p>\n<p>L'op\u00e9rateur utilitaire share peut transformer un flux froid en un flux chaud. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmation asynchrone en JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c46e96420ed78d197ceef829ff74c82d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Nous avons termin\u00e9 avec les op\u00e9rateurs. Passons au Subject.<\/p>\n<p>\n<b class=\"spoiler_title\">R\u00e9flexion<\/b><\/p>\n<p>Et l\u00e0, je suis all\u00e9 prendre un th\u00e9. Ces exemples m'ont fatigu\u00e9 \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">La famille des subjects<\/h2>\n<p><\/p>\n<p>La famille des subjects est un exemple frappant de flux chauds. Ces classes sont en quelque sorte des hybrides, agissant \u00e0 la fois comme observable et observer. \u00c9tant donn\u00e9 que le subject est un flux chaud, il est n\u00e9cessaire de s'y d\u00e9sabonner. En ce qui concerne les principales m\u00e9thodes, les voici :<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 envoi de nouvelles donn\u00e9es dans le flux<\/li>\n<li>error \u2013 erreur et terminaison du flux<\/li>\n<li>complete \u2013 terminaison du flux<\/li>\n<li>subscribe \u2013 s'abonner au flux<\/li>\n<li>unsubscribe \u2013 se d\u00e9sabonner du flux<\/li>\n<li>asObservable \u2013 transform\u00e9 en observateur<\/li>\n<li>toPromise \u2013 transform\u00e9 en promesse<\/li>\n<\/ul>\n<p><\/p>\n<p>On distingue 4 ou 5 types de subjects. <\/p>\n<p>\n<b class=\"spoiler_title\">R\u00e9flexion<\/b><\/p>\n<p>J'ai parl\u00e9 de 4 lors du stream, mais apparemment ils en ont ajout\u00e9 un de plus. Comme on dit, on vit et on apprend.<\/p>\n<p><\/p>\n<p>Subject simple <code>new Subject()<\/code>\u2013 le type de subject le plus simple. Cr\u00e9\u00e9 sans param\u00e8tres. Transmet les valeurs re\u00e7ues uniquement apr\u00e8s l'abonnement.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject(defaultData)<\/code> \u2013 \u00e0 mon avis, le type de subject le plus couramment utilis\u00e9. Prend en entr\u00e9e une valeur par d\u00e9faut. Toujours conserve les donn\u00e9es de la derni\u00e8re \u00e9mission, qui sont transmises lors de l'abonnement. Cette classe poss\u00e8de \u00e9galement la m\u00e9thode utile value, qui retourne la valeur actuelle du flux.<\/p>\n<p><\/p>\n<p>ReplaySubject <code>new ReplaySubject(bufferSize?: number, windowTime?: number)<\/code> \u2014 En entr\u00e9e, il peut optionnellement prendre comme premier argument la taille du buffer des valeurs qu'il va stocker, et comme deuxi\u00e8me le temps pendant lequel nous avons besoin des modifications.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> \u2014 lors de l'abonnement, rien ne se passe, et la valeur sera retourn\u00e9e uniquement lors de complete. Seule la derni\u00e8re valeur du flux sera retourn\u00e9e.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig | Observable, destination?: Observer)<\/code> \u2014 La documentation est silencieuse \u00e0 son sujet et je le vois pour la premi\u00e8re fois. Qui sait ce qu'il fait, \u00e9crivez, nous compl\u00e9terons.<\/p>\n<p><\/p>\n<p>Ouf. Eh bien, nous avons couvert tout ce que je voulais dire aujourd'hui. J'esp\u00e8re que cette information a \u00e9t\u00e9 utile. Vous pouvez consulter la bibliographie dans l'onglet informations utiles.<\/p>\n<p><\/p>\n<h2 id=\"poleznaya-informaciya\">Informations utiles<\/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 lien vers le 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 Comment fonctionne JS : aper\u00e7u du moteur, des m\u00e9canismes d'ex\u00e9cution, de la pile d'appels<\/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 Comment fonctionne JS : boucle d'\u00e9v\u00e9nements, asynchronisme et cinq fa\u00e7ons d'am\u00e9liorer le code avec 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 Comment fonctionne la boucle d'\u00e9v\u00e9nements en JavaScript<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/tproger.ru\/translations\/asynchronous-javascript\/\">https:\/\/tproger.ru\/translations\/asynchronous-javascript\/<\/a><\/noindex> \u2014 L'\u00e9volution de JavaScript asynchrone<\/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 Qu'est-ce que RxJS et pourquoi est-il utile de le conna\u00eetre<\/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 Applications pratiques de 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 Tutoriel RxJS Observables \u2014 Cr\u00e9ation et abonnement aux Observables<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/slides.com\/zenabsaleem\/rxjs-hot-cold-observables#\/\">https:\/\/slides.com\/zenabsaleem\/rxjs-hot-cold-observables#\/<\/a><\/noindex> \u2014 RXJS : Observables chauds et froids<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FiPgB\">https:\/\/clck.ru\/FiPgB<\/a><\/noindex> \u2014 Classes, fonctions pour cr\u00e9er des Observable. Op\u00e9rateurs.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.learnrxjs.io\/operators\/\">https:\/\/www.learnrxjs.io\/operators\/<\/a><\/noindex> \u2014 Op\u00e9rateurs RxJS par exemple<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/rxjs.dev\/api\">https:\/\/rxjs.dev\/api<\/a><\/noindex> \u2014 Liste API<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FkS8Y\">https:\/\/clck.ru\/FkS8Y<\/a><\/noindex> \u2014 Types de Subject et Scheduling dans RxJS<\/li>\n<\/ul>\n<p>Source : <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/462355\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u041e\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u043a\u0438\u0439 \u0421\u0435\u0440\u0433\u0435\u0439. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0432\u0435\u043b \u0441\u0442\u0440\u0438\u043c \u043f\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0432 JavaScript. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u043a\u043e\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b. \u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0432\u043e\u0434\u043d\u0443\u044e. \u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0439: \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0441\u0442\u0435\u043a \u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u044c? \u0421\u0442\u0435\u043a \u2014 \u044d\u0442\u043e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f, \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0439 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27545,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-36774","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u041e\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u043a\u0438\u0439 \u0421\u0435\u0440\u0433\u0435\u0439. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0432\u0435\u043b \u0441\u0442\u0440\u0438\u043c \u043f\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0432 JavaScript. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u043a\u043e\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/fr\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"fr_FR\" \/>\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\/fr\/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\udd47Programmation asynchrone en JavaScript. (Callback, Promise, RxJs) | ProHoster","description":"Bonjour \u00e0 tous. Ici, Sergey Omelnitsky. Il n'y a pas si longtemps, j'ai anim\u00e9 un stream sur la programmation r\u00e9active, o\u00f9 j'ai parl\u00e9 de l'asynchrone en JavaScript. Aujourd'hui, je voudrais r\u00e9sumer ce mat\u00e9riel.","canonical_url":"https:\/\/prohoster.info\/fr\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"fr_FR","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\/fr\/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\/fr\/wp-json\/wp\/v2\/posts\/36774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/comments?post=36774"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/posts\/36774\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media\/27545"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/media?parent=36774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/categories?post=36774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/fr\/wp-json\/wp\/v2\/tags?post=36774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}