{"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\/it\/blog\/novosti-interneta\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","title":{"rendered":"Programmazione asincrona in JavaScript. ( Callback, Promise, RxJs )","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ciao a tutti. Qui \u00e8 Sergey Omelnytsky. Di recente ho tenuto uno streaming sulla programmazione reattiva, in cui ho parlato dell'asincronicit\u00e0 in JavaScript. Oggi vorrei riassumere questo materiale. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Ma prima di iniziare il materiale principale, dobbiamo fare un'introduzione. Iniziamo quindi con le definizioni: cosa sono lo stack e la coda?<br \/>\n<strong>Stack <\/strong>\u00e8 una collezione i cui elementi vengono acquisiti secondo il principio \u00abultimo ad entrare, primo ad uscire\u00bb LIFO<br \/>\n<strong>Coda <\/strong>\u00e8 una collezione i cui elementi vengono acquisiti secondo il principio \u00abprimo ad entrare, primo ad uscire\u00bb FIFO<\/p>\n<p><\/p>\n<p>Ok, continuiamo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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 \u00e8 un linguaggio di programmazione a thread singolo. Questo significa che ha solo un thread di esecuzione e uno stack in cui le funzioni vengono messe in coda per l'esecuzione. Di conseguenza, in un dato momento, JavaScript pu\u00f2 eseguire solo un'operazione; le altre operazioni devono aspettare il loro turno nello stack fino a quando non vengono chiamate. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Stack delle chiamate<\/strong> \u2014 \u00e8 una struttura dati che, semplificando, registra informazioni sul punto in cui ci troviamo nel programma. Se entriamo in una funzione, mettiamo una registrazione di essa in cima allo stack. Quando usciamo dalla funzione, estraiamo l'elemento in cima allo stack e torniamo al punto da cui abbiamo chiamato quella funzione. Questo \u00e8 tutto ci\u00f2 che fa uno stack. Ora, c'\u00e8 una domanda molto interessante. Come funziona l'asynchronousit\u00e0 in JavaScript?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>In realt\u00e0, oltre allo stack, nei browser esiste una coda speciale per gestire il cosiddetto WebAPI. Le funzioni in questa coda verranno eseguite in ordine solo dopo che lo stack sar\u00e0 completamente vuoto. Solo allora vengono spostate dalla coda allo stack per l'esecuzione. Se al momento c'\u00e8 almeno un elemento nello stack, non possono entrare nello stack. \u00c8 proprio per questo motivo che le chiamate alle funzioni con timeout spesso non sono precise nel tempo, poich\u00e9 la funzione non pu\u00f2 entrare nello stack finch\u00e9 esso \u00e8 pieno. <\/p>\n<p><\/p>\n<p>Consideriamo il seguente esempio e seguiamo la sua 'esecuzione' passo per passo. Andiamo a vedere cosa succede nel sistema durante questo processo.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">console.log('Ciao');\nsetTimeout(function cb1() {\n    console.log('cb1');\n}, 5000);\nconsole.log('Arrivederci');<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) All'inizio non succede nulla. La console del browser \u00e8 vuota, lo stack delle chiamate \u00e8 vuoto.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) \u041f\u043e\u0442\u043e\u043c \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u00a0console.log(&#8216;Hi&#8217;)\u00a0\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u0442\u0435\u043a \u0432\u044b\u0437\u043e\u0432\u043e\u0432.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) E viene eseguito.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) \u0417\u0430\u0442\u0435\u043c console.log(&#8216;Hi&#8217;) \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0432\u044b\u0437\u043e\u0432\u043e\u0432.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) Ora passiamo al comando setTimeout(function cb1() {\u2026 }). Viene aggiunto allo stack delle chiamate.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) Il comando setTimeout(function cb1() {\u2026 }) viene eseguito. Il browser crea un timer, che fa parte delle Web API. Inizier\u00e0 il conto alla rovescia.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) Il comando setTimeout(function cb1() {\u2026 }) ha completato l'esecuzione e viene rimosso dallo stack delle chiamate.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) \u041a\u043e\u043c\u0430\u043d\u0434\u0430\u00a0console.log(&#8216;Bye&#8217;)\u00a0\u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u0441\u0442\u0435\u043a \u0432\u044b\u0437\u043e\u0432\u043e\u0432.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) \u041a\u043e\u043c\u0430\u043d\u0434\u0430\u00a0console.log(&#8216;Bye&#8217;)\u00a0\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) \u041a\u043e\u043c\u0430\u043d\u0434\u0430\u00a0console.log(&#8216;Bye&#8217;)\u00a0\u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0432\u044b\u0437\u043e\u0432\u043e\u0432.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) Dopo che sono trascorsi almeno 5000 ms, il timer termina e colloca il callback cb1 nella coda dei callback.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) Il ciclo degli eventi prende la funzione cb1 dalla coda dei callback e la mette nello stack delle chiamate.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) \u0424\u0443\u043d\u043a\u0446\u0438\u044f\u00a0cb1\u00a0\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u00a0console.log(&#8216;cb1&#8217;)\u00a0\u0432 \u0441\u0442\u0435\u043a \u0432\u044b\u0437\u043e\u0432\u043e\u0432.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) \u041a\u043e\u043c\u0430\u043d\u0434\u0430\u00a0console.log(&#8216;cb1&#8217;)\u00a0\u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) \u041a\u043e\u043c\u0430\u043d\u0434\u0430\u00a0console.log(&#8216;cb1&#8217;)\u00a0\u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f \u0438\u0437 \u0441\u0442\u0435\u043a\u0430 \u0432\u044b\u0437\u043e\u0432\u043e\u0432.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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) La funzione cb1 viene rimossa dallo stack delle chiamate.<\/p>\n<p><\/p>\n<p>Diamo un'occhiata a un esempio in azione:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Bene, abbiamo esplorato come l'asincronia \u00e8 implementata in JavaScript. Ora parliamo brevemente dell'evoluzione del codice asincrono.<\/p>\n<p><\/p>\n<h2 id=\"evolyuciya-asinhronnogo-koda\">Evoluzione del codice asincrono.<\/h2>\n<p><\/p>\n<pre><code class=\"javascript\">a(function (risultatiDaA) {\n    b(risultatiDaA, function (risultatiDaB) {\n        c(risultatiDaB, function (risultatiDaC) {\n            d(risultatiDaC, function (risultatiDaD) {\n                e(risultatiDaD, function (risultatiDaE) {\n                    f(risultatiDaE, function (risultatiDaF) {\n                        console.log(risultatiDaF);\n                    })\n                })\n            })\n        })\n    })\n});<\/code><\/pre>\n<p><\/p>\n<p>La programmazione asincrona, cos\u00ec come la conosciamo in JavaScript, pu\u00f2 essere realizzata solo tramite funzioni. Queste possono essere passate come qualsiasi altra variabile ad altre funzioni. Cos\u00ec sono nati i callback. \u00c8 tutto divertente e spassoso fino a quando non si trasforma in tristezza e malinconia. Perch\u00e9?<\/p>\n<p><\/p>\n<ul>\n<li>Con l'aumento della complessit\u00e0 del codice, il progetto si trasforma rapidamente in blocchi multipli annidati e poco comprensibili \u2014 il 'callback hell'.<\/li>\n<li>La gestione degli errori pu\u00f2 facilmente essere trascurata.<\/li>\n<li>Non \u00e8 possibile restituire espressioni con return.<\/li>\n<\/ul>\n<p><\/p>\n<p>Con l'arrivo delle Promise, la situazione \u00e8 migliorata un po'.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">nuova 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('FALLIMENTO QUI');\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('errore: ', e);\n});<\/code><\/pre>\n<p><\/p>\n<ul>\n<li>Sono emerse catene di promesse, il che ha migliorato la leggibilit\u00e0 del codice.<\/li>\n<li>\u00c8 stato introdotto un metodo separato per la gestione degli errori.<\/li>\n<li>\u00c8 stata introdotta la possibilit\u00e0 di esecuzione parallela con Promise.all.<\/li>\n<li>Possiamo gestire la nidificazione asincrona utilizzando async\/await.<\/li>\n<\/ul>\n<p><\/p>\n<p>Ma la promessa ha i suoi limiti. Ad esempio, una promessa non pu\u00f2 essere annullata senza complicate manovre e, cosa pi\u00f9 importante, lavora con un solo valore.<\/p>\n<p><\/p>\n<p>Ecco, siamo arrivati gradualmente alla programmazione reattiva. Stanchi? Bene, potete andare a preparare un t\u00e8, riflettere e tornare a continuare a leggere. Io intanto proseguir\u00f2.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Programmazione reattiva<\/strong>\u200a\u2014\u200auna paradigma di programmazione focalizzata sui flussi di dati e sulla diffusione delle modifiche. Analizziamo pi\u00f9 nel dettaglio cosa si intende per flusso di dati.<\/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>Immagina di avere un campo di input. Creiamo un array e, per ogni evento keyup sull'input, salveremo l'evento nel nostro array. \u00c8 importante notare che il nostro array \u00e8 ordinato per tempo, cio\u00e8 l'indice degli eventi pi\u00f9 recenti \u00e8 maggiore di quello degli eventi pi\u00f9 vecchi. Questo array rappresenta una versione semplificata del flusso dei dati, ma non \u00e8 ancora un flusso. Affinch\u00e9 questo array possa essere definito come un flusso, deve in qualche modo essere in grado di informare gli iscritti che sono arrivati nuovi dati. Cos\u00ec siamo arrivati alla definizione di flusso.<\/p>\n<p><\/p>\n<h3 id=\"potok-dannyh\">Flusso di dati<\/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=\"Programmazione asincrona 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>Flusso<\/strong>\u00e8 un array di dati ordinati per tempo, che pu\u00f2 comunicare che i dati sono cambiati. Ora immagina quanto sia comodo scrivere codice in cui un'azione richiede di innescare pi\u00f9 eventi in diverse parti del codice. Basta iscriversi al flusso e ci informer\u00e0 automaticamente quando ci sono modifiche. E questo \u00e8 ci\u00f2 che fa la libreria RxJs.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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 \u00e8 una libreria per lavorare con programmi asincroni e basati su eventi utilizzando sequenze osservabili. La libreria fornisce un tipo principale <em>Observable<\/em>, diversi tipi ausiliari (<em>Observer, Schedulers, Subjects<\/em>) e operatori per lavorare con eventi come collezioni (<em>map, filter, reduce, every<\/em> e simili da JavaScript Array).<\/p>\n<p><\/p>\n<p>Esploriamo i concetti fondamentali di questa libreria.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable \u00e8 il primo tipo di base che esamineremo. Questa classe contiene la parte fondamentale dell'implementazione di RxJs. \u00c8 collegata a un flusso osservabile, al quale \u00e8 possibile iscriversi utilizzando il metodo subscribe.<\/p>\n<p><\/p>\n<p>In Observable \u00e8 implementato un meccanismo ausiliario per la creazione di aggiornamenti, chiamato <em>Observer<\/em>. La sorgente dei valori per l'Observer si chiama <em>Producer<\/em>. Questo pu\u00f2 essere un array, un iteratore, un web socket, un evento, ecc. Quindi si pu\u00f2 dire che l'observable \u00e8 un conduttore tra Producer e Observer. <\/p>\n<p><\/p>\n<p>Observable gestisce tre tipi di eventi per l'Observer:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 nuovi dati<\/li>\n<li>error \u2013 un errore, se la sequenza \u00e8 terminata a causa di una situazione eccezionale. Questo evento implica anch'esso la conclusione della sequenza.<\/li>\n<li>completo \u2014 segnale di fine sequenza. Ci\u00f2 significa che non ci saranno pi\u00f9 nuovi dati.<\/li>\n<\/ul>\n<p><\/p>\n<p>Diamo un'occhiata alla demo:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Inizialmente elaboreremo i valori 1, 2, 3, e dopo 1 secondo riceveremo 4 e chiuderemo il nostro flusso.<\/p>\n<p>\n<b class=\"spoiler_title\">Pensieri ad alta voce<\/b><\/p>\n<p>E qui ho capito che raccontare era pi\u00f9 interessante che scrivere. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Abbonamento<\/h3>\n<p><\/p>\n<p>Quando ci abboniamo a un flusso, creiamo una nuova classe <strong>abbonamento<\/strong>, che ci consente di annullare l'abbonamento usando il metodo <em>annulla iscrizione<\/em>. Possiamo anche raggruppare gli abbonamenti tramite il metodo <em>add<\/em>. E, ovviamente, possiamo anche disaggregare i flussi tramite <em>rimuovi<\/em>. I metodi add e remove accettano come input un altro abbonamento. \u00c8 importante notare che quando ci disiscriviamo, ci disiscriveremo anche da tutti gli abbonamenti secondari come se avessimo chiamato il metodo annulla iscrizione su di essi. Andiamo avanti.<\/p>\n<p><\/p>\n<h3 id=\"vidy-potokov\">Tipi di flussi<\/h3>\n<p><\/p>\n<table>\n<thead>\n<tr>\n<th>CALDO<\/th>\n<th>FREDDO<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Il produttore viene creato all'esterno dell'observable<\/td>\n<td>Il produttore viene creato all'interno dell'observable<\/td>\n<\/tr>\n<tr>\n<td>I dati vengono trasmessi al momento della creazione dell'observable<\/td>\n<td>I dati vengono comunicati al momento dell'iscrizione<\/td>\n<\/tr>\n<tr>\n<td>\u00c8 necessaria una logica aggiuntiva per la disiscrizione<\/td>\n<td>Il flusso si conclude autonomamente<\/td>\n<\/tr>\n<tr>\n<td>Utilizza una relazione uno-a-molti<\/td>\n<td>Utilizza una relazione uno-a-uno<\/td>\n<\/tr>\n<tr>\n<td>Tutti gli abbonamenti hanno un valore comune<\/td>\n<td>Gli abbonamenti sono indipendenti<\/td>\n<\/tr>\n<tr>\n<td>I dati possono andare persi se non c'\u00e8 abbonamento<\/td>\n<td>Riproduce tutti i valori dello stream per un nuovo abbonamento<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Se dovessi fare un'analogia, immaginerai lo stream caldo come un film al cinema. Il momento in cui arrivi determina da dove inizi a guardare. Lo stream freddo lo paragonerei a una chiamata al supporto tecnico. Chiunque chiami ascolta la registrazione dell'auto-risponditore dall'inizio alla fine, ma puoi riattaccare con un unsubscribe.<\/p>\n<p><\/p>\n<p>Mi piacerebbe sottolineare che esistono anche i cosiddetti stream warm (una definizione che ho trovato raramente e solo in comunit\u00e0 straniere) \u2014 \u00e8 uno stream che si trasforma da freddo a caldo. Nasce quindi la domanda: dove usarlo?)) Far\u00f2 un esempio dalla pratica.<\/p>\n<p><\/p>\n<p>Lavoro con Angular. Utilizza attivamente RxJS. Per ottenere dati dal server, mi aspetto un flusso freddo e utilizzo questo flusso nel template con asyncPipe. Se utilizzo questo pipe pi\u00f9 volte, tornando alla definizione di flusso freddo, ogni pipe richieder\u00e0 dati dal server, il che \u00e8, per cos\u00ec dire, strano. Ma se trasformo un flusso freddo in uno caldo, la richiesta avverr\u00e0 solo una volta.<\/p>\n<p><\/p>\n<p>In generale, comprendere i tipi di flussi \u00e8 abbastanza complesso per i principianti, ma \u00e8 importante. <\/p>\n<p><\/p>\n<h3 id=\"operators\">Operatori<\/h3>\n<p><\/p>\n<pre><code class=\"javascript\">return this.http.get(`${environment.apiUrl}\/${this.apiUrl}\/trade_companies`)\n    .pipe(\n        tap(({ data }: TradeCompanyList) =&gt; this.companies$$.next(cloneDeep(data))),\n        map(({ data }: TradeCompanyList) =&gt; data)\n    );<\/code><\/pre>\n<p><\/p>\n<p>Gli operatori ci offrono la possibilit\u00e0 di lavorare con i flussi. Aiutano a controllare gli eventi che avvengono in un Observable. Esamineremo alcuni dei pi\u00f9 popolari, mentre ulteriori dettagli sugli operatori possono essere trovati nei link delle informazioni utili.<\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 of<\/strong><\/p>\n<p><\/p>\n<p>Iniziamo con l'operatore ausiliario of. Crea un Observable basato su un valore semplice.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Operatori \u2014 filter<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>L'operatore di filtraggio filter, come si pu\u00f2 intuire dal nome, filtra il segnale del flusso. Se l'operatore restituisce vero, allora lo lascia passare.<\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 take<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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 Riceve il numero di emissioni dopo il quale la sequenza si completa.<\/p>\n<p><\/p>\n<p><strong>Operatori \u2014 debounceTime<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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 scarta i valori emessi che arrivano in un intervallo di tempo specificato tra le emissioni \u2014 dopo il tempo stabilito, emette l'ultimo valore.<\/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  \/\/ Emissione di un valore ogni 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n\n  \/\/ Emissione di un valore ogni 1500ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1500);\n}).pipe(\n  debounceTime(700),  \/\/ Aspetta 700ms di valori prima di elaborare\n  take(3)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Operatori \u2014 takeWhile<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Emette valori finch\u00e9 takeWhile non restituisce false, dopodich\u00e9 si disiscrive dalla sequenza.<\/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  \/\/ Emissione di un valore ogni 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n}).pipe(\n  takeWhile(producer =&gt; producer &lt; 5)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Operatori \u2014 combineLatest<\/strong><\/p>\n<p><\/p>\n<p>L'operatore combineLatest \u00e8 simile a promise.all. Combina pi\u00f9 flussi in uno. Dopo che ogni flusso ha emesso almeno un valore, otteniamo gli ultimi valori da ciascuno sotto forma di array. Inoltre, dopo qualsiasi emissione dai flussi combinati, restituir\u00e0 nuovi valori.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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  \/\/ Emesso un valore ogni 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  \/\/ Emesso un valore ogni 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=\"Programmazione asincrona 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>Operatori \u2014 zip<\/strong><\/p>\n<p><\/p>\n<p>Zip attende un valore da ciascun flusso e forma un array basato su questi valori. Se un valore non proviene da un flusso, il gruppo non sar\u00e0 formato.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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  \/\/ Emission 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  \/\/ Emission 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  \/\/ Emission 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=\"Programmazione asincrona 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 unisce anche i flussi, ma emette un valore solo quando tutti i flussi sono completati.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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  \/\/ Emission 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  \/\/ Emission 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  \/\/ Emission 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=\"Programmazione asincrona 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>L'operatore di trasformazione map altera il valore emesso in uno nuovo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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  \/\/ Emission every 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++);\n  }, 1000);\n}).pipe(\n  map(x =&gt; x * 10),\n  take(3)\n);\n<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Operatori \u2013 share, tap<\/strong><\/p>\n<p><\/p>\n<p>\u041e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 tap\u00a0&#8212; \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0434\u0435\u043b\u0430\u0442\u044c side \u044d\u0444\u0444\u0435\u043a\u0442\u044b, \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u0430\u043a\u0438\u0435-\u043b\u0438\u0431\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u0432\u043b\u0438\u044f\u044e\u0442 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p><\/p>\n<p>L'operatore utilitario share \u00e8 in grado di trasformare un flusso freddo in uno caldo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programmazione asincrona 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>Abbiamo terminato con gli operatori. Passiamo a Subject.<\/p>\n<p>\n<b class=\"spoiler_title\">Pensieri ad alta voce<\/b><\/p>\n<p>E qui sono andato a bere un t\u00e8. Questi esempi mi hanno stancato \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">Famiglia di subject<\/h2>\n<p><\/p>\n<p>La famiglia di subject \u00e8 un chiaro esempio di flussi caldi. Queste classi sono una sorta di ibrido, che fungono sia da observable che da observer. Poich\u00e9 un subject \u00e8 un flusso caldo, \u00e8 necessario disiscriversi da esso. Parlando dei metodi principali, ecco:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 inviare nuovi dati nel flusso<\/li>\n<li>error \u2013 errore e conclusione del flusso<\/li>\n<li>complete \u2013 conclusione del flusso<\/li>\n<li>subscribe \u2013 iscriversi al flusso<\/li>\n<li>unsubscribe \u2013 disiscriversi dal flusso<\/li>\n<li>asObservable \u2013 trasformare in observable<\/li>\n<li>toPromise \u2013 trasformare in promesse<\/li>\n<\/ul>\n<p><\/p>\n<p>Si distinguono 4 o 5 tipi di subject. <\/p>\n<p>\n<b class=\"spoiler_title\">Pensieri ad alta voce<\/b><\/p>\n<p>Nel live streaming ho detto 4, ma si \u00e8 scoperto che ne hanno aggiunto un altro. Come si suol dire, vivi e impara.<\/p>\n<p><\/p>\n<p>Subject semplice <code>new Subject()<\/code>\u2013 il tipo pi\u00f9 semplice di subject. Viene creato senza parametri. Trasmette valori ricevuti solo dopo l'iscrizione.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject(defaultData)<\/code> \u2013 secondo me, \u00e8 il tipo di subject pi\u00f9 comune. Accetta un valore predefinito. Memorizza sempre i dati dell'ultima emissione, che vengono inviati all'iscrizione. Questa classe ha anche un metodo utile, value, che restituisce il valore attuale del flusso.<\/p>\n<p><\/p>\n<p>ReplaySubject <code>new ReplaySubject(bufferSize?: number, windowTime?: number)<\/code> \u2013 pu\u00f2 accettare opzionalmente come primo argomento la dimensione del buffer dei valori che conserver\u00e0, e come secondo il tempo durante il quale sono necessari i cambiamenti.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> \u2013 all'iscrizione non succede nulla, e il valore verr\u00e0 restituito solo al termine. Verr\u00e0 restituito solo l'ultimo valore del flusso.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig | Observable, destination?: Observer)<\/code> \u2013 la documentazione non dice nulla su di lui e lo vedo per la prima volta. Chi sa cosa fa, scriva e lo completeremo.<\/p>\n<p><\/p>\n<p>Fatto. Bene, abbiamo esaminato tutto ci\u00f2 di cui volevo parlare oggi. Spero che queste informazioni siano state utili. Puoi consultare la lista di riferimento nella scheda 'informazioni utili'.<\/p>\n<p><\/p>\n<h2 id=\"poleznaya-informaciya\">Informazioni utili<\/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 allo 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 Come funziona JS: panoramica del motore, meccanismi di esecuzione, stack delle chiamate<\/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 Come funziona JS: ciclo degli eventi, asincronicit\u00e0 e cinque modi per migliorare il codice con 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 Come funziona l'Event Loop in JavaScript<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/tproger.ru\/translations\/asynchronous-javascript\/\">https:\/\/tproger.ru\/translations\/asynchronous-javascript\/<\/a><\/noindex> \u2014 Evoluzione di JavaScript asincrono<\/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 Cos'\u00e8 RxJS e perch\u00e9 \u00e8 utile conoscerlo<\/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 Applicazioni pratiche di 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 Tutorial su RxJS Observables \u2014 Creazione e iscrizione a 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: Observable Hot e Cold<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FiPgB\">https:\/\/clck.ru\/FiPgB<\/a><\/noindex> \u2014 Classi, funzioni per creare Observable. Operatori.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.learnrxjs.io\/operators\/\">https:\/\/www.learnrxjs.io\/operators\/<\/a><\/noindex> \u2014 Esempi di operatori RxJS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/rxjs.dev\/api\">https:\/\/rxjs.dev\/api<\/a><\/noindex> \u2014 Lista API<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FkS8Y\">https:\/\/clck.ru\/FkS8Y<\/a><\/noindex> \u2014 Tipi di Subject e Scheduling in RxJS<\/li>\n<\/ul>\n<p>Fonte: <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\/it\/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=\"it_IT\" \/>\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\/it\/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\udd47Programmazione asincrona in JavaScript. (Callback, Promise, RxJs) | ProHoster","description":"Ciao a tutti. Sono Omelnytskyi Serhii. Non molto tempo fa ho condotto uno streaming sulla programmazione reattiva, in cui ho parlato dell'asincronia in JavaScript. Oggi vorrei riassumere questo materiale. Ma prima di iniziare il materiale principale, dobbiamo fare un'introduzione. Quindi, cominciamo con le definizioni: cosa sono lo stack e la coda? Lo stack \u00e8 una collezione i cui elementi","canonical_url":"https:\/\/prohoster.info\/it\/blog\/novosti-interneta\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"it_IT","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\/it\/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\/it\/wp-json\/wp\/v2\/posts\/36774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/comments?post=36774"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/posts\/36774\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media\/27545"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/media?parent=36774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/categories?post=36774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/it\/wp-json\/wp\/v2\/tags?post=36774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}