{"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\/pt\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","title":{"rendered":"Programa\u00e7\u00e3o ass\u00edncrona em JavaScript. (Callback, Promise, RxJs)","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Ol\u00e1 a todos. Aqui \u00e9 o Sergey Omelnytsky. N\u00e3o faz muito tempo, fiz uma transmiss\u00e3o ao vivo sobre programa\u00e7\u00e3o reativa, onde falei sobre assincronidade em JavaScript. Hoje, gostaria de resumir esse material. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/11acf6af8328d3deb6f0ce48e813efb7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Mas antes de come\u00e7armos o conte\u00fado principal, precisamos fazer uma introdu\u00e7\u00e3o. Ent\u00e3o, vamos come\u00e7ar com defini\u00e7\u00f5es: o que s\u00e3o pilha e fila?<br \/>\n<strong>Pilha <\/strong>\u2014 \u00e9 uma cole\u00e7\u00e3o cujos elementos s\u00e3o obtidos segundo o princ\u00edpio \"\u00faltimo a entrar, primeiro a sair\" (LIFO).<br \/>\n<strong>Fila <\/strong>\u2014 \u00e9 uma cole\u00e7\u00e3o cujos elementos s\u00e3o obtidos segundo o princ\u00edpio \"primeiro a entrar, primeiro a sair\" (FIFO).<\/p>\n<p><\/p>\n<p>Ok, vamos continuar. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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 \u00e9 uma linguagem de programa\u00e7\u00e3o de thread \u00fanica. Isso significa que h\u00e1 apenas uma thread de execu\u00e7\u00e3o e uma pilha, na qual as fun\u00e7\u00f5es s\u00e3o colocadas em espera para serem executadas. Portanto, em um determinado momento, JavaScript s\u00f3 pode executar uma opera\u00e7\u00e3o; outras opera\u00e7\u00f5es ficar\u00e3o aguardando sua vez na pilha at\u00e9 serem chamadas. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Pilha de chamadas<\/strong> \u2014 \u00e9 uma estrutura de dados que, de forma simplificada, grava informa\u00e7\u00f5es sobre onde estamos no programa. Se entramos em uma fun\u00e7\u00e3o, colocamos uma entrada sobre ela na parte superior da pilha. Quando retornamos de uma fun\u00e7\u00e3o, removemos o elemento do topo da pilha e voltamos ao ponto de onde chamamos essa fun\u00e7\u00e3o. Isso \u00e9 tudo o que a pilha faz. Agora, surge uma pergunta muito interessante. Como, ent\u00e3o, a assincronidade funciona em JavaScript?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/a29fd1dd3de06fb203c7dd14bda30548.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Na verdade, al\u00e9m da pilha, os navegadores t\u00eam uma fila especial para trabalhar com o chamado WebAPI. As fun\u00e7\u00f5es dessa fila ser\u00e3o executadas em ordem apenas depois que a pilha estiver completamente limpa. Somente ap\u00f3s isso, elas s\u00e3o transferidas da fila para a pilha para execu\u00e7\u00e3o. Se houver pelo menos um elemento na pilha, elas n\u00e3o poder\u00e3o entrar na pilha. \u00c9 exatamente por isso que a chamada de fun\u00e7\u00f5es de timeout muitas vezes n\u00e3o \u00e9 precisa em termos de tempo, j\u00e1 que a fun\u00e7\u00e3o n\u00e3o pode ir da fila para a pilha enquanto esta estiver cheia. <\/p>\n<p><\/p>\n<p>Vamos considerar o seguinte exemplo e analis\u00e1-lo passo a passo. Tamb\u00e9m veremos o que est\u00e1 acontecendo no sistema durante isso.<\/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=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) Enquanto nada acontece. O console do navegador est\u00e1 limpo, a pilha de chamadas est\u00e1 vazia.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) Em seguida, o comando console.log(\u2018Hi\u2019) \u00e9 adicionado \u00e0 pilha de chamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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 ela \u00e9 executada<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) Depois, console.log(\u2018Hi\u2019) \u00e9 removido da pilha de chamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) Agora passamos para o comando setTimeout(function cb1() {\u2026 }). Ele \u00e9 adicionado \u00e0 pilha de chamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) O comando setTimeout(function cb1() {\u2026 }) \u00e9 executado. O navegador cria um temporizador, que \u00e9 parte da API Web. Ele come\u00e7ar\u00e1 a contagem regressiva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) O comando setTimeout(function cb1() {\u2026 }) terminou e \u00e9 removido da pilha de chamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) O comando console.log(\u2018Bye\u2019) \u00e9 adicionado \u00e0 pilha de chamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) O comando console.log(\u2018Bye\u2019) \u00e9 executado.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) O comando console.log(\u2018Bye\u2019) \u00e9 removido da pilha de chamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) Depois que pelo menos 5000 ms passarem, o temporizador termina e coloca o callback cb1 na fila de callbacks.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) O loop de eventos pega a fun\u00e7\u00e3o cb1 da fila de callbacks e a coloca na pilha de chamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) A fun\u00e7\u00e3o cb1 \u00e9 executada e adiciona console.log(\u2018cb1\u2019) \u00e0 pilha de chamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) O comando console.log(\u2018cb1\u2019) \u00e9 executado.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) O comando console.log(\u2018cb1\u2019) \u00e9 removido da pilha de chamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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) A fun\u00e7\u00e3o cb1 \u00e9 removida da pilha de chamadas.<\/p>\n<p><\/p>\n<p>Vamos olhar para um exemplo em a\u00e7\u00e3o:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/3836d9df513afee374f498720990e39f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>E assim, examinamos como a ass\u00edncronicidade \u00e9 implementada em JavaScript. Agora, vamos falar brevemente sobre a evolu\u00e7\u00e3o do c\u00f3digo ass\u00edncrono.<\/p>\n<p><\/p>\n<h2 id=\"evolyuciya-asinhronnogo-koda\">Evolu\u00e7\u00e3o do c\u00f3digo ass\u00edncrono.<\/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>A programa\u00e7\u00e3o ass\u00edncrona, como conhecemos em JavaScript, pode ser implementada apenas com fun\u00e7\u00f5es. Elas podem ser passadas como qualquer outra vari\u00e1vel para outras fun\u00e7\u00f5es. Assim, nasceram os callbacks. E isso \u00e9 legal, divertido e emocionante, at\u00e9 que se transforma em tristeza e desespero. Por qu\u00ea? \u00c9 simples:<\/p>\n<p><\/p>\n<ul>\n<li>Com o aumento da complexidade do c\u00f3digo, o projeto rapidamente se transforma em blocos aninhados dif\u00edceis de entender \u2014 o 'callback hell'.<\/li>\n<li>O tratamento de erros pode ser facilmente negligenciado.<\/li>\n<li>N\u00e3o se pode devolver express\u00f5es com return.<\/li>\n<\/ul>\n<p><\/p>\n<p>Com o surgimento das Promises, a situa\u00e7\u00e3o melhorou um pouco.<\/p>\n<p><\/p>\n<pre><code class=\"javascript\">new Promise(function(resolve, reject) {\n    setTimeout(() =&gt; resolve(1), 2000);\n\n}).then((result) =&gt; {\n    alert(result);\n    return result + 2;\n\n}).then((result) =&gt; {\n    throw new Error('FAILED HERE');\n    alert(result);\n    return result + 2;\n\n}).then((result) =&gt; {\n    alert(result);\n    return result + 2;\n\n}).catch((e) =&gt; {\n    console.log('error: ', e);\n});<\/code><\/pre>\n<p><\/p>\n<ul>\n<li>As cadeias de promessas surgiram, melhorando a legibilidade do c\u00f3digo.<\/li>\n<li>Um m\u00e9todo separado para captura de erros foi introduzido.<\/li>\n<li>Agora \u00e9 poss\u00edvel a execu\u00e7\u00e3o paralela com Promise.all<\/li>\n<li>Podemos resolver a aninhamento ass\u00edncrono com async\/await<\/li>\n<\/ul>\n<p><\/p>\n<p>Mas a promessa tem suas limita\u00e7\u00f5es. Por exemplo, uma promessa n\u00e3o pode ser cancelada sem muitos truques, e o mais importante \u2014 ela trabalha com um \u00fanico valor.<\/p>\n<p><\/p>\n<p>Assim, chegamos suavemente \u00e0 programa\u00e7\u00e3o reativa. Est\u00e1 cansado? Bem, voc\u00ea pode ir fazer um ch\u00e1, pensar um pouco e voltar a ler. Eu continuarei.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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>Programa\u00e7\u00e3o reativa<\/strong>\u200a\u2014\u200a\u00e9 uma paradigma de programa\u00e7\u00e3o focado em fluxos de dados e propaga\u00e7\u00e3o de mudan\u00e7as. Vamos analisar mais detalhadamente o que \u00e9 um fluxo de dados.<\/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>Vamos imaginar que temos um campo de entrada. Criamos um array e, a cada evento keyup do input, salvamos o evento neste array. Observamos que nosso array est\u00e1 ordenado por tempo, ou seja, o \u00edndice dos eventos mais recentes \u00e9 maior que o \u00edndice dos eventos mais antigos. Esse array representa um modelo simplificado de um fluxo de dados, mas ainda n\u00e3o \u00e9 um fluxo. Para que esse array possa ser considerado um fluxo, ele deve conseguir de alguma forma informar aos assinantes que novos dados foram recebidos. Assim, chegamos \u00e0 defini\u00e7\u00e3o de um fluxo.<\/p>\n<p><\/p>\n<h3 id=\"potok-dannyh\">Fluxo de dados<\/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=\"Programa\u00e7\u00e3o ass\u00edncrona em 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>Fluxo\u200a<\/strong>\u2014\u200a\u00e9 um array de dados ordenado por tempo que pode comunicar quando os dados foram alterados. Agora imagine como se torna conveniente escrever c\u00f3digo em que uma a\u00e7\u00e3o requer a chamada de v\u00e1rios eventos em diferentes partes do c\u00f3digo. N\u00f3s apenas nos inscrevemos no fluxo e ele nos avisa quando ocorrem mudan\u00e7as. E \u00e9 isso que a biblioteca RxJs pode fazer.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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 \u00e9 uma biblioteca para trabalhar com programas ass\u00edncronos e baseados em eventos usando sequ\u00eancias observ\u00e1veis. A biblioteca fornece o tipo principal <em>Observable<\/em>, v\u00e1rios tipos auxiliares (<em>Observer, Schedulers, Subjects<\/em>) e operadores para trabalhar com eventos como cole\u00e7\u00f5es (<em>map, filter, reduce, every<\/em> e semelhantes do Array JavaScript).<\/p>\n<p><\/p>\n<p>Vamos entender os conceitos b\u00e1sicos desta biblioteca.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable \u2014 \u00e9 o primeiro tipo b\u00e1sico que examinaremos. Esta classe cont\u00e9m a parte principal da implementa\u00e7\u00e3o do RxJs. Ela est\u00e1 relacionada ao fluxo observ\u00e1vel, no qual voc\u00ea pode se inscrever usando o m\u00e9todo subscribe.<\/p>\n<p><\/p>\n<p>No Observable implementa um mecanismo auxiliar para gerar atualiza\u00e7\u00f5es, conhecido como <em>Observer<\/em>. A fonte de valores para o Observer \u00e9 chamada de <em>Producer<\/em>. Isso pode ser um array, um iterador, um web socket, um evento, etc. Portanto, podemos dizer que o observable \u00e9 um condutor entre Producer e Observer. <\/p>\n<p><\/p>\n<p>O Observable processa tr\u00eas tipos de eventos do Observer:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 novos dados<\/li>\n<li>error \u2013 um erro, se a sequ\u00eancia for conclu\u00edda devido a uma situa\u00e7\u00e3o excepcional. Este evento tamb\u00e9m implica a conclus\u00e3o da sequ\u00eancia.<\/li>\n<li>complete \u2014 um sinal de que a sequ\u00eancia foi conclu\u00edda. Isso significa que n\u00e3o haver\u00e1 mais novos dados<\/li>\n<\/ul>\n<p><\/p>\n<p>Vamos ver uma demonstra\u00e7\u00e3o:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c5bcd2af0f18b6de3ab0dbc20db595d1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>No come\u00e7o, processaremos os valores 1, 2, 3, e ap\u00f3s 1 segundo, receberemos 4 e finalizaremos nosso fluxo.<\/p>\n<p>\n<b class=\"spoiler_title\">Pensando em voz alta<\/b><\/p>\n<p>E aqui percebi que era mais interessante contar do que escrever sobre isso. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Subscription<\/h3>\n<p><\/p>\n<p>Quando fazemos uma assinatura no fluxo, criamos uma nova classe <strong>subscription<\/strong>, que nos permite cancelar a assinatura usando o m\u00e9todo <em>unsubscribe<\/em>. Tamb\u00e9m podemos agrupar assinaturas usando o m\u00e9todo <em>add<\/em>. E \u00e9 l\u00f3gico que podemos desagrupar fluxos usando <em>remover<\/em>. Os m\u00e9todos add e remove aceitam outra assinatura como entrada. Vale ressaltar que, quando cancelamos a assinatura, estamos cancelando todas as assinaturas filhas como se tiv\u00e9ssemos chamado o m\u00e9todo unsubscribe nelas. Vamos em frente.<\/p>\n<p><\/p>\n<h3 id=\"vidy-potokov\">Tipos de fluxos<\/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>O Producer \u00e9 criado fora do observable<\/td>\n<td>O Producer \u00e9 criado dentro do observable<\/td>\n<\/tr>\n<tr>\n<td>Os dados s\u00e3o transmitidos no momento da cria\u00e7\u00e3o do observable<\/td>\n<td>Os dados s\u00e3o comunicados no momento da assinatura<\/td>\n<\/tr>\n<tr>\n<td>\u00c9 necess\u00e1ria l\u00f3gica adicional para o cancelamento da assinatura<\/td>\n<td>O fluxo se encerra sozinho<\/td>\n<\/tr>\n<tr>\n<td>Usa uma rela\u00e7\u00e3o um-para-muitos<\/td>\n<td>Usa uma rela\u00e7\u00e3o um-para-um<\/td>\n<\/tr>\n<tr>\n<td>Todas as assinaturas t\u00eam um valor \u00fanico<\/td>\n<td>As assinaturas s\u00e3o independentes<\/td>\n<\/tr>\n<tr>\n<td>Os dados podem ser perdidos se n\u00e3o houver assinatura<\/td>\n<td>Reemiti todos os valores do fluxo para uma nova assinatura<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Se eu fizer uma analogia, eu representaria um fluxo quente como um filme no cinema. No momento em que voc\u00ea chega, come\u00e7a a assistir a partir daquele ponto. Um fluxo frio eu compararia a uma chamada para a assist\u00eancia t\u00e9cnica. Qualquer pessoa que ligar ouve a grava\u00e7\u00e3o do correio de voz do come\u00e7o ao fim, mas voc\u00ea pode desligar com o m\u00e9todo unsubscribe.<\/p>\n<p><\/p>\n<p>Gostaria de observar que existem tamb\u00e9m os chamados fluxos quentes (essa defini\u00e7\u00e3o que encontrei raramente e apenas em comunidades estrangeiras) \u2014 este \u00e9 um fluxo que se transforma de um fluxo frio em um quente. Surge a pergunta \u2014 onde usar isso? Vou dar um exemplo da pr\u00e1tica.<\/p>\n<p><\/p>\n<p>Eu trabalho com Angular. Ele utiliza ativamente o RxJS. Para obter dados no servidor, espero um fluxo frio e utilizo esse fluxo no template com o asyncPipe. Se eu usar esse pipe v\u00e1rias vezes, voltando \u00e0 defini\u00e7\u00e3o de fluxo frio, cada pipe ir\u00e1 solicitar dados do servidor, o que, para dizer o m\u00ednimo, \u00e9 estranho. E se eu transformar o fluxo frio em quente, a solicita\u00e7\u00e3o ocorrer\u00e1 uma \u00fanica vez.<\/p>\n<p><\/p>\n<p>Na verdade, a compreens\u00e3o dos tipos de fluxos \u00e9 bastante complexa para iniciantes, mas importante. <\/p>\n<p><\/p>\n<h3 id=\"operators\">Operadores<\/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>Os operadores nos fornecem a capacidade de trabalhar com fluxos. Eles ajudam a controlar os eventos que ocorrem em um Observable. Vamos considerar alguns dos mais populares; para mais detalhes sobre os operadores, voc\u00ea pode consultar os links nas informa\u00e7\u00f5es \u00fateis.<\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 of<\/strong><\/p>\n<p><\/p>\n<p>Vamos come\u00e7ar com o operador auxiliar of. Ele cria um Observable com base em um valor simples.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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>Operadores \u2014 filter<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/24ac65fdb5ccc7f6301b3dfe49f1e804.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>O operador de filtragem filter, como o pr\u00f3prio nome sugere, filtra o sinal do fluxo. Se o operador retornar verdadeiro, ele passa adiante.<\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 take<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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 Aceita um n\u00famero de emiss\u00f5es, ap\u00f3s o qual o fluxo \u00e9 encerrado.<\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 debounceTime<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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 descarta os valores emitidos que ocorrem dentro de um intervalo de tempo especificado entre as sa\u00eddas \u2014 ap\u00f3s o intervalo de tempo, emite o \u00faltimo valor.<\/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  \/\/ Emite um valor a cada 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n\n  \/\/ Emite um valor a cada 1500ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1500);\n}).pipe(\n  debounceTime(700),  \/\/ Espera 700ms pelos valores antes de process\u00e1-los\n  take(3)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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>Operadores \u2014 takeWhile<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/120d9fe6ddf5a60ddffc8742989b27ff.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Emite valores enquanto takeWhile n\u00e3o retornar falso, ap\u00f3s o que se desinscreve do fluxo.<\/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  \/\/ Emite um valor a cada 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=\"Programa\u00e7\u00e3o ass\u00edncrona em 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>Operadores \u2014 combineLatest<\/strong><\/p>\n<p><\/p>\n<p>O operador combinado combineLatest \u00e9 semelhante ao promise.all. Ele combina v\u00e1rios fluxos em um s\u00f3. Assim que cada fluxo emite pelo menos uma vez, obtemos os \u00faltimos valores de cada um na forma de um array. Em seguida, ap\u00f3s qualquer emiss\u00e3o dos fluxos combinados, ele retornar\u00e1 novos valores.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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  \/\/ Emite um valor a cada 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  \/\/ Emite um valor a cada 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=\"Programa\u00e7\u00e3o ass\u00edncrona em 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>Operadores \u2014 zip<\/strong><\/p>\n<p><\/p>\n<p>Zip espera um valor de cada fluxo e forma um array baseado nesses valores. Se um valor n\u00e3o for recebido de um dos fluxos, o grupo n\u00e3o ser\u00e1 formado.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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  \/\/ Emite um valor a cada 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  \/\/ Emite um valor a cada 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  \/\/ Emite um valor a cada 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=\"Programa\u00e7\u00e3o ass\u00edncrona em 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>Operadores \u2014 forkJoin<\/strong><\/p>\n<p><\/p>\n<p>forkJoin tamb\u00e9m combina fluxos, mas ele emite um valor somente quando todos os fluxos est\u00e3o completos.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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  \/\/ Emite um valor a cada 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  \/\/ Emite um valor a cada 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  \/\/ Emite um valor a cada 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=\"Programa\u00e7\u00e3o ass\u00edncrona em 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>Operadores \u2014 map<\/strong><\/p>\n<p><\/p>\n<p>O operador de transforma\u00e7\u00e3o map converte o valor emitido em um novo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em 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  \/\/ Emite um valor a cada 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=\"Programa\u00e7\u00e3o ass\u00edncrona em 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>Operadores \u2014 share, tap<\/strong><\/p>\n<p><\/p>\n<p>O operador tap \u2014 permite realizar efeitos colaterais, ou seja, a\u00e7\u00f5es que n\u00e3o afetam a sequ\u00eancia.<\/p>\n<p><\/p>\n<p>O operador utilit\u00e1rio share \u00e9 capaz de transformar um fluxo frio em um quente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programa\u00e7\u00e3o ass\u00edncrona em JavaScript. (Callback, Promise, RxJs)\" src=\"\/wp-content\/uploads\/2019\/08\/c46e96420ed78d197ceef829ff74c82d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Terminamos com os operadores. Vamos passar para o Subject.<\/p>\n<p>\n<b class=\"spoiler_title\">Pensando em voz alta<\/b><\/p>\n<p>E aqui fui eu tomar um ch\u00e1. Esses exemplos me cansaram \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">Fam\u00edlia de subjects<\/h2>\n<p><\/p>\n<p>A fam\u00edlia de subjects \u00e9 um exemplo claro de fluxos quentes. Essas classes s\u00e3o uma esp\u00e9cie de h\u00edbrido que atuam simultaneamente como observable e observer. Como o subject \u00e9 um fluxo quente, \u00e9 necess\u00e1rio cancelar a inscri\u00e7\u00e3o. Falando sobre os principais m\u00e9todos, temos:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 transmiss\u00e3o de novos dados no fluxo<\/li>\n<li>error \u2013 erro e finaliza\u00e7\u00e3o do fluxo<\/li>\n<li>complete \u2013 finaliza\u00e7\u00e3o do fluxo<\/li>\n<li>subscribe \u2013 inscrever-se no fluxo<\/li>\n<li>unsubscribe \u2013 cancelar a inscri\u00e7\u00e3o no fluxo<\/li>\n<li>asObservable \u2013 transforma em um observador<\/li>\n<li>toPromise \u2013 transforma em uma promessa<\/li>\n<\/ul>\n<p><\/p>\n<p>Diferenciam-se 4 a 5 tipos de subjects. <\/p>\n<p>\n<b class=\"spoiler_title\">Pensando em voz alta<\/b><\/p>\n<p>Na transmiss\u00e3o, mencionei 4, mas parece que adicionaram mais um. Como diz o ditado, viver \u00e9 aprender.<\/p>\n<p><\/p>\n<p>Subject simples <code>new Subject()<\/code>\u2013 \u00e9 o tipo mais simples de subject. \u00c9 criado sem par\u00e2metros. Transmite valores recebidos apenas ap\u00f3s a inscri\u00e7\u00e3o.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject(defaultData)<\/code> \u2013 na minha opini\u00e3o, \u00e9 o tipo mais comum de subjects. Recebe um valor padr\u00e3o como entrada. Sempre mant\u00e9m os dados da \u00faltima emiss\u00e3o, que s\u00e3o transmitidos na inscri\u00e7\u00e3o. Esta classe tamb\u00e9m possui um m\u00e9todo \u00fatil chamado value, que retorna o valor atual do fluxo.<\/p>\n<p><\/p>\n<p>ReplaySubject <code>new ReplaySubject(bufferSize?: number, windowTime?: number)<\/code> \u2013 Como entrada, pode opcionalmente aceitar o tamanho do buffer de valores que manter\u00e1 como primeiro argumento e, como segundo, o tempo durante o qual as altera\u00e7\u00f5es s\u00e3o necess\u00e1rias.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> \u2013 ao se inscrever, nada acontece, e o valor ser\u00e1 retornado apenas na finaliza\u00e7\u00e3o. Apenas o \u00faltimo valor do fluxo ser\u00e1 retornado.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig | Observable, destination?: Observer)<\/code> \u2013 A documenta\u00e7\u00e3o n\u00e3o menciona nada sobre ele e eu o vejo pela primeira vez. Se algu\u00e9m souber o que ele faz, escreva, vamos complementar.<\/p>\n<p><\/p>\n<p>Uf, bem, assim discutimos tudo o que eu queria falar hoje. Espero que esta informa\u00e7\u00e3o tenha sido \u00fatil. Voc\u00ea pode consultar a lista de refer\u00eancias na aba de informa\u00e7\u00f5es \u00fateis.<\/p>\n<p><\/p>\n<h2 id=\"poleznaya-informaciya\">Informa\u00e7\u00e3o \u00fatil<\/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 para a transmiss\u00e3o<\/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 Como funciona o JS: vis\u00e3o geral do motor, mecanismos de execu\u00e7\u00e3o, pilha de chamadas<\/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 Como funciona o JS: ciclo de eventos, ass\u00edncrono e cinco maneiras de melhorar o c\u00f3digo com 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 Como funciona o Event Loop no JavaScript<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/tproger.ru\/translations\/asynchronous-javascript\/\">https:\/\/tproger.ru\/translations\/asynchronous-javascript\/<\/a><\/noindex> \u2014 A evolu\u00e7\u00e3o do JavaScript ass\u00edncrono<\/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 O que \u00e9 RxJS e por que \u00e9 \u00fatil saber sobre ele<\/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 Aplica\u00e7\u00e3o pr\u00e1tica do 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 de Observables RxJS \u2014 Criando &amp; Inscrevendo-se em 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 Quentes e Frios<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FiPgB\">https:\/\/clck.ru\/FiPgB<\/a><\/noindex> \u2014 Classes, fun\u00e7\u00f5es para criar Observable. Operadores.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.learnrxjs.io\/operators\/\">https:\/\/www.learnrxjs.io\/operators\/<\/a><\/noindex> \u2014 Operadores RxJS por Exemplo<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/rxjs.dev\/api\">https:\/\/rxjs.dev\/api<\/a><\/noindex> \u2014 Lista de API<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FkS8Y\">https:\/\/clck.ru\/FkS8Y<\/a><\/noindex> \u2014 Tipos de Subject e Agendas no 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.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u041e\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u043a\u0438\u0439 \u0421\u0435\u0440\u0433\u0435\u0439. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0432\u0435\u043b \u0441\u0442\u0440\u0438\u043c \u043f\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0432 JavaScript. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u043a\u043e\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/pt\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"pt_PT\" \/>\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\/pt\/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\udd47Programa\u00e7\u00e3o ass\u00edncrona em JavaScript. (Callback, Promise, RxJs) | ProHoster","description":"Ol\u00e1 a todos. Aqui \u00e9 o Sergey Omelnytsky. N\u00e3o faz muito tempo, fiz uma transmiss\u00e3o ao vivo sobre programa\u00e7\u00e3o reativa, onde falei sobre assincronidade em JavaScript. Hoje, gostaria de resumir esse material.","canonical_url":"https:\/\/prohoster.info\/pt\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"pt_PT","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\/pt\/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\/pt\/wp-json\/wp\/v2\/posts\/36774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/comments?post=36774"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/posts\/36774\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media\/27545"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/media?parent=36774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/categories?post=36774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/pt\/wp-json\/wp\/v2\/tags?post=36774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}