{"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\/news\/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. Sono Sergey Omelnitsky. Non molto tempo fa ho tenuto uno streaming sulla programmazione reattiva, dove 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. Quindi, iniziamo con le definizioni: che cos'\u00e8 uno stack e una coda?<br \/>\n<strong>Stack <\/strong>\u00e8 una collezione i cui elementi vengono ottenuti secondo il principio \"ultimo entrato, primo uscito\" LIFO<br \/>\n<strong>Coda <\/strong>\u00e8 una collezione i cui elementi vengono ottenuti secondo il principio \"primo entrato, primo uscito\" 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 esiste solo un flusso 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, mentre le altre operazioni devono attendere il loro turno nello stack finch\u00e9 non vengono chiamate. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Stack delle chiamate<\/strong> \u00e8 una struttura dati che, semplificando, registra informazioni sul luogo nel programma in cui ci troviamo. Se entriamo in una funzione, posizioniamo una registrazione di essa nella parte superiore dello stack. Quando ritorniamo dalla funzione, estraiamo il pi\u00f9 alto elemento dallo stack e ci troviamo nel punto da cui abbiamo chiamato quella funzione. Questo \u00e8 tutto quello che sa fare uno stack. E ora, una domanda molto interessante. Come funziona allora l'asincronicit\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 particolare coda per lavorare con il cosiddetto WebAPI. Le funzioni di 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 attualmente nello stack c'\u00e8 almeno un elemento, non possono entrare nello stack. \u00c8 proprio per questo che la chiamata delle funzioni con timeout \u00e8 spesso imprecisa nel tempo, poich\u00e9 la funzione non pu\u00f2 entrare nello stack dalla coda finch\u00e9 \u00e8 pieno. <\/p>\n<p><\/p>\n<p>Consideriamo il seguente esempio e affrontiamo il suo \"esecuzione\" passo dopo passo. Inoltre, vediamo cosa sta accadendo nel sistema.<\/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=\"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) Non succede niente. La console del browser \u00e8 pulita, 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) Poi il comando console.log('Hi') viene aggiunto allo stack di chiamate.<\/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) Successivamente, console.log('Hi') viene rimosso dallo stack di chiamate.<\/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 \u00e8 parte delle Web API. Inizier\u00e0 il conteggio 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 terminato l'esecuzione ed \u00e8 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) Il comando console.log('Bye') viene aggiunto allo stack di chiamate.<\/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) Il comando console.log('Bye') 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\/09e4e380eb873fb23bea550f3ffb21f7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>10) Il comando console.log('Bye') viene rimosso dallo stack di chiamate.<\/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 almeno 5000 ms, il timer termina l'esecuzione e inserisce 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 inserisce 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) La funzione cb1 viene eseguita e aggiunge console.log('cb1') allo stack di chiamate.<\/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) Il comando console.log('cb1') 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\/0caa645a90ac1fca5fb8a76569494d48.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>15) Il comando console.log('cb1') viene rimosso dallo stack di chiamate.<\/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 dinamica:<\/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>Cos\u00ec abbiamo esaminato come in JavaScript \u00e8 realizzata l'asincronia. 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 (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 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. Ed \u00e8 divertente, allegro e spensierato, finch\u00e9 non si trasforma in tristezza, malinconia e dolore. Perch\u00e9? \u00c8 semplice:<\/p>\n<p><\/p>\n<ul>\n<li>Con l'aumento della complessit\u00e0 del codice, il progetto si trasforma rapidamente in blocchi annidati poco comprensibili: il 'callback hell'.<\/li>\n<li>La gestione degli errori pu\u00f2 essere facilmente trascurata.<\/li>\n<li>Non \u00e8 possibile restituire espressioni con return.<\/li>\n<\/ul>\n<p><\/p>\n<p>Con l'avvento dei Promise, la situazione \u00e8 migliorata un po'.<\/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('FALLITO 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 state introdotte 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 resa possibile l'esecuzione parallela tramite Promise.all.<\/li>\n<li>Possiamo risolvere l'asincronicit\u00e0 annidata usando async\/await<\/li>\n<\/ul>\n<p><\/p>\n<p>Ma un promise ha le sue limitazioni. Ad esempio, un promise, senza particolari trucchi, non pu\u00f2 essere annullato 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, puoi sempre andare a preparare un t\u00e8, riflettere e tornare a leggere. Io continuer\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\u200a\u00e8 un paradigma di programmazione orientato ai flussi di dati e alla propagazione delle modifiche. Approfondiamo pi\u00f9 dettagliatamente 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>Immaginiamo di avere un campo di input. Creiamo un array e ad ogni evento keyup dell\u2019input salveremo l'evento nel nostro array. Desidero sottolineare che il nostro array \u00e8 ordinato per tempo\u200a, cio\u00e8\u200a l'indice degli eventi pi\u00f9 recenti \u00e8 maggiore di quello degli eventi precedenti. Questo array rappresenta un modello semplificato di flusso di dati, ma non \u00e8 ancora un flusso. Affinch\u00e9 questo array possa essere chiamato flusso, deve essere in grado in qualche modo di comunicare agli abbonati che sono stati ricevuti nuovi dati. Cos\u00ec siamo giunti 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\u200a<\/strong>\u2014\u200a\u00e8 un array di dati ordinati nel tempo, in grado di comunicare che i dati sono cambiati. Ora immagina quanto diventa comodo scrivere codice in cui, per un'azione, \u00e8 necessario generare diversi eventi in diverse parti del codice. Ci abboniamo semplicemente al flusso e lui ci informer\u00e0 da solo quando ci saranno cambiamenti. E questo \u00e8 ci\u00f2 che sa fare 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 il tipo principale <em>Observable<\/em>, alcuni tipi ausiliari (<em>Observer, Schedulers, Subjects<\/em>) e operatori per lavorare con eventi come collezioni (<em>map, filter, reduce, every<\/em> e simili dell'Array di JavaScript).<\/p>\n<p><\/p>\n<p>Esaminiamo i concetti di base di questa libreria.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable \u2014 il primo tipo di base che tratteremo. Questa classe contiene la parte fondamentale dell'implementazione di RxJs. \u00c8 legata a un flusso osservabile, al quale si pu\u00f2 abbonarsi tramite il metodo subscribe.<\/p>\n<p><\/p>\n<p>In Observable viene implementato un meccanismo ausiliario per creare aggiornamenti, noto come <em>Observer<\/em>. La fonte di valori per l'Observer \u00e8 chiamata <em>Produttore<\/em>. Questo pu\u00f2 essere un array, un iteratore, un web socket, un evento, ecc. Quindi si pu\u00f2 dire che l'observable funge da intermediario tra Producer e Observer. <\/p>\n<p><\/p>\n<p>Observable gestisce tre tipi di eventi dell'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 un'eccezione. Questo evento implica anche la conclusione della sequenza.<\/li>\n<li>complete \u2014 segnale di conclusione della sequenza. Questo significa che non ci saranno pi\u00f9 nuovi dati.<\/li>\n<\/ul>\n<p><\/p>\n<p>Vediamo una 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>All'inizio elaboreremo i valori 1, 2, 3, e dopo 1 secondo riceveremo 4 e concluderemo il nostro flusso.<\/p>\n<p>\n<b class=\"spoiler_title\">Pensando ad alta voce<\/b><\/p>\n<p>E qui ho capito che raccontare era pi\u00f9 interessante che scriverne. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Subscription<\/h3>\n<p><\/p>\n<p>Quando ci iscrivi a un flusso, creiamo un nuovo <strong>subscription<\/strong>, che ci consente di annullare l'iscrizione tramite il metodo <em>unsubscribe<\/em>. Possiamo anche raggruppare le iscrizioni tramite il metodo <em>add<\/em>. \u00c8 logico che possiamo disaggregare i flussi tramite <em>remove<\/em>. I metodi add e remove accettano un'altra iscrizione. Vorrei notare che quando ci disiscrivi, ti disiscrivi da tutte le sottoscrizioni figlie come se avessi chiamato il metodo unsubscribe anche per loro. 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>HOT<\/th>\n<th>COLD<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Il Producer \u00e8 creato esternamente all'observable<\/td>\n<td>Il Producer \u00e8 creato internamente all'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 logica aggiuntiva per la disiscrizione<\/td>\n<td>Il flusso termina autonomamente<\/td>\n<\/tr>\n<tr>\n<td>Utilizza la relazione uno-a-molti<\/td>\n<td>Utilizza la relazione uno-a-uno<\/td>\n<\/tr>\n<tr>\n<td>Tutte le iscrizioni hanno un valore unico<\/td>\n<td>Le iscrizioni sono indipendenti<\/td>\n<\/tr>\n<tr>\n<td>I dati possono andare persi se non c'\u00e8 iscrizione<\/td>\n<td>Rilascia tutti i valori del flusso per una nuova iscrizione<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Se dovessimo fare un'analogia, rappresenterei il flusso caldo come un film al cinema. Da quale momento arrivi, inizi a guardare da quel punto. Il flusso freddo lo paragonerei a una chiamata al supporto tecnico. Chiunque chiami ascolta la registrazione del centralinista dall'inizio alla fine, ma puoi riagganciare tramite unsubscribe.<\/p>\n<p><\/p>\n<p>Vorrei sottolineare che ci sono anche i cosiddetti flussi caldi (questa definizione l'ho incontrata molto raramente e solo in comunit\u00e0 straniere) \u2014 \u00e8 un flusso che si trasforma da un flusso freddo in uno caldo. Si pone quindi la domanda: dove utilizzarlo?)) Porter\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 tramite asyncPipe. Se utilizzo questo pipe pi\u00f9 volte, tornando alla definizione di flusso freddo, ogni pipe richieder\u00e0 i dati al server, il che \u00e8, per dirla in modo educato, strano. Ma se trasformo un flusso freddo in caldo, la richiesta avverr\u00e0 una sola volta.<\/p>\n<p><\/p>\n<p>In generale, la comprensione dei tipi di flussi \u00e8 abbastanza complessa per i principianti, ma \u00e8 importante. <\/p>\n<p><\/p>\n<h3 id=\"operators\">Operators<\/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 forniscono maggiori possibilit\u00e0 di lavorare con i flussi. Aiutano a controllare gli eventi che fluiscono negli Observable. Esamineremo alcuni dei pi\u00f9 popolari, mentre per maggiori dettagli sugli operatori puoi consultare i link nelle informazioni utili.<\/p>\n<p><\/p>\n<p><strong>Operators \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>Operators \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 capire dal nome, filtra il segnale del flusso. Se l'operatore restituisce vero, il segnale passa oltre.<\/p>\n<p><\/p>\n<p><strong>Operators \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 Accetta il numero di emissioni dopo il quale il flusso termina.<\/p>\n<p><\/p>\n<p><strong>Operators \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 si presentano entro l'intervallo di tempo specificato tra i dati in uscita \u2014 dopo il trascorrere dell'intervallo di tempo 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),  \/\/ Aspettiamo 700ms per il valore prima di elaborarlo\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>Operators \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 falso, dopodich\u00e9 si disconnette dal flusso.<\/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  \/\/ Emitto 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 combinato combineLatest \u00e8 simile a promise.all. Combina pi\u00f9 flussi in uno. Una volta che ogni flusso ha emesso almeno un valore, otteniamo gli ultimi valori da ciascuno come un array. In seguito, dopo ogni emissione da uno dei 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  \/\/ Emitto 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  \/\/ Emitto 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 in base a questi valori. Se un valore non arriva da un flusso, il gruppo non verr\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  \/\/ Emitto 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  \/\/ Emitto un valore ogni 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  \/\/ Emitto un valore ogni 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>Operatori \u2014 forkJoin<\/strong><\/p>\n<p><\/p>\n<p>forkJoin combina anche i flussi, ma emette un valore solo quando tutti i flussi sono stati completati (complete).<\/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  \/\/ Emitto un valore ogni 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  \/\/ Emitto un valore ogni 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  \/\/ Emitto un valore ogni 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>Operatori \u2014 map<\/strong><\/p>\n<p><\/p>\n<p>L'operatore di trasformazione map trasforma 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  \/\/ Emitto un valore ogni 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>L'operatore tap \u2014 consente di effettuare effetti collaterali, ovvero azioni che non influenzano la sequenza.<\/p>\n<p><\/p>\n<p>L'operatore utility 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 finito con gli operatori. Passiamo al Subject.<\/p>\n<p>\n<b class=\"spoiler_title\">Pensando ad alta voce<\/b><\/p>\n<p>E qui sono andato a bere un t\u00e8. Questi esempi mi hanno esausto \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">La famiglia dei subject<\/h2>\n<p><\/p>\n<p>La famiglia dei subject \u00e8 un chiaro esempio di flussi caldi. Queste classi sono una sorta di ibrido che funge sia da observable che da observer. Poich\u00e9 il subject \u00e8 un flusso caldo, \u00e8 necessario disiscriversi da esso. Parlando dei principali metodi, abbiamo:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 invio di nuovi dati al flusso<\/li>\n<li>error \u2013 errore e termine 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 osservabile<\/li>\n<li>toPromise \u2013 trasformare in promessa<\/li>\n<\/ul>\n<p><\/p>\n<p>Si distinguono 4-5 tipi di subject. <\/p>\n<p>\n<b class=\"spoiler_title\">Pensando ad alta voce<\/b><\/p>\n<p>Durante la diretta ho parlato di 4, ma si \u00e8 scoperto che ne hanno aggiunto un altro. Come si dice, chi vive 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 solo i valori ricevuti dopo l'iscrizione.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject(defaultData&lt;T&gt;)<\/code> \u2013 a mio avviso il tipo di subject pi\u00f9 comune. Accetta un valore predefinito. Salva sempre l'ultimo dato emesso, che trasmette all'iscrizione. Questa classe ha anche un metodo utile chiamato 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 di valori che manterr\u00e0 e come secondo l'intervallo di tempo per cui sono necessari gli aggiornamenti.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> \u2013 all'iscrizione non accade nulla, e il valore verr\u00e0 restituito solo al termine. Solo l'ultimo valore del flusso verr\u00e0 restituito.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig&lt;T&gt; | Observable&lt;T&gt;, destination?: Observer&lt;T&gt;)<\/code> \u2013 La documentazione tace su di lui e lo vedo per la prima volta. Se qualcuno sa cosa fa, scrivetelo, completeremo.<\/p>\n<p><\/p>\n<p>Uff. Bene, abbiamo esaminato tutto ci\u00f2 che volevo raccontare oggi. Spero che queste informazioni siano state utili. \u00c8 possibile consultare autonomamente l'elenco di letture 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> \u2013 link alla diretta<\/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> \u2013 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, asincronia 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 Applicazione pratica 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 RxJS Observables \u2014 Creazione e Iscrizione agli 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 Caldi e Freddi<\/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 Operatori RxJS per Esempio<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/rxjs.dev\/api\">https:\/\/rxjs.dev\/api<\/a><\/noindex> \u2014 Elenco API<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FkS8Y\">https:\/\/clck.ru\/FkS8Y<\/a><\/noindex> \u2014 Tipi di Subject e Pianificazioni 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-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.1.1 - 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\/it\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.1.1\" \/>\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.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/it\/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\udd47Programmazione asincrona in JavaScript. (Callback, Promise, RxJs) | ProHoster","description":"Ciao a tutti. Sono Sergey Omelnitsky. Non molto tempo fa ho tenuto uno streaming sulla programmazione reattiva, dove ho parlato dell'asincronicit\u00e0 in JavaScript. Oggi vorrei riassumere questo materiale.","canonical_url":"https:\/\/prohoster.info\/it\/blog\/news\/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.","og:url":"https:\/\/prohoster.info\/it\/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\/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}]}}