{"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\/es\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","title":{"rendered":"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>Hola a todos. Soy Sergey Omelnitsky. No hace mucho, realic\u00e9 una transmisi\u00f3n en vivo sobre programaci\u00f3n reactiva, donde habl\u00e9 sobre la asincron\u00eda en JavaScript. Hoy me gustar\u00eda resumir este material. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/11acf6af8328d3deb6f0ce48e813efb7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Pero antes de comenzar con el material principal, necesitamos hacer una introducci\u00f3n. As\u00ed que, empecemos con definiciones: \u00bfqu\u00e9 es una pila y una cola?<br \/>\n<strong>Pila <\/strong>es una colecci\u00f3n cuyos elementos se obtienen seg\u00fan el principio de \u00ab\u00faltimo en entrar, primero en salir\u00bb LIFO.<br \/>\n<strong>Cola <\/strong>es una colecci\u00f3n cuyos elementos se obtienen seg\u00fan el principio de \u00abprimero en entrar, primero en salir\u00bb FIFO.<\/p>\n<p><\/p>\n<p>Est\u00e1 bien, continuemos. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/a7d64d1c74f37b463869dd57b96c9d0e.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>JavaScript es un lenguaje de programaci\u00f3n de un solo hilo. Esto significa que tiene un solo hilo de ejecuci\u00f3n y una sola pila, en la cual se colocan las funciones en cola para su ejecuci\u00f3n. Por lo tanto, en un momento dado, JavaScript solo puede ejecutar una operaci\u00f3n, las otras operaciones esperar\u00e1n su turno en la pila hasta que sean llamadas. <\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p><strong>Pila de llamadas<\/strong> es una estructura de datos que, simplificando, registra informaci\u00f3n sobre el lugar en el programa donde nos encontramos. Si entramos en una funci\u00f3n, colocamos un registro de ella en la parte superior de la pila. Cuando regresamos de la funci\u00f3n, sacamos el elemento m\u00e1s alto de la pila y retornamos al punto donde se llam\u00f3 a esa funci\u00f3n. Eso es todo lo que puede hacer una pila. Y ahora surge una pregunta muy interesante. \u00bfC\u00f3mo funciona entonces la asincron\u00eda en JavaScript?<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/a29fd1dd3de06fb203c7dd14bda30548.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>En realidad, adem\u00e1s de la pila, en los navegadores hay una cola especial para trabajar con lo que se llama WebAPI. Las funciones de esta cola se ejecutan en orden solo despu\u00e9s de que la pila est\u00e9 completamente vac\u00eda. Solo despu\u00e9s de eso se trasladan de la cola a la pila para su ejecuci\u00f3n. Si en la pila hay al menos un elemento, no pueden entrar en la pila. Precisamente por eso, la llamada a funciones con timeout a menudo no es precisa en el tiempo, ya que una funci\u00f3n no puede pasar de la cola a la pila mientras esta est\u00e9 ocupada. <\/p>\n<p><\/p>\n<p>Veamos el siguiente ejemplo y abordemos su \u00abejecuci\u00f3n\u00bb paso a paso. Tambi\u00e9n analicemos qu\u00e9 sucede en el sistema en ese momento.<\/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=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/379423fca95fb28b2124be03dfd15739.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>1) Por ahora, no sucede nada. La consola del navegador est\u00e1 limpia, y la pila de llamadas est\u00e1 vac\u00eda.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/4a16bbc23bade54ae0b02d81d5f6a581.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>2) Luego, el comando console.log('Hi') se a\u00f1ade a la pila de llamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/a1845af23fd7dedebf94afc168f1f13f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>3) Y se ejecuta.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/57397b53386018b662f3a79a6d4d60fb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>4) A continuaci\u00f3n, console.log('Hi') se elimina de la pila de llamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/7cb2b32be8807ecf39d2f38683ccd435.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>5) Ahora pasamos al comando setTimeout(function cb1() {\u2026 }). Este se a\u00f1ade a la pila de llamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/99c0724994e3390d009577852b451beb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>6) El comando setTimeout(function cb1() {\u2026 }) se ejecuta. El navegador crea un temporizador, que es parte de la API web. Este har\u00e1 una cuenta regresiva.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/99086cdeafd83c5fe72e92c4a9f9b738.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>7) El comando setTimeout(function cb1() {\u2026 }) ha terminado y se elimina de la pila de llamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/24ac12b1b6cfbff780ece9e9a7acd7c7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>8) El comando console.log('Bye') se a\u00f1ade a la pila de llamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/6ccad0ad8eebf05e870a409766d38766.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>9) El comando console.log('Bye') se ejecuta.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/09e4e380eb873fb23bea550f3ffb21f7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>10) El comando console.log('Bye') se elimina de la pila de llamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/357bfb372361310681ba7bb1860d90d7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>11) Despu\u00e9s de al menos 5000 ms, el temporizador termina y coloca el callback cb1 en la cola de callbacks.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/8170e8ff5d3d0c56c0091658370c25cc.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>12) El ciclo de eventos toma la funci\u00f3n cb1 de la cola de callbacks y la coloca en la pila de llamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/d858a54e82bc32d84f854610db462bc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>13) La funci\u00f3n cb1 se ejecuta y a\u00f1ade console.log('cb1') a la pila de llamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/6ca8e016389904eec57035e64d57a157.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>14) El comando console.log('cb1') se ejecuta.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/0caa645a90ac1fca5fb8a76569494d48.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>15) El comando console.log('cb1') se elimina de la pila de llamadas.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/aeb838fe8df3f6e3f8603a4207a6e193.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>16) La funci\u00f3n cb1 se elimina de la pila de llamadas.<\/p>\n<p><\/p>\n<p>Veamos un ejemplo en din\u00e1mica:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/3836d9df513afee374f498720990e39f.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Ya hemos discutido c\u00f3mo se implementa la asincron\u00eda en JavaScript. Ahora hablemos brevemente sobre la evoluci\u00f3n del c\u00f3digo as\u00edncrono.<\/p>\n<p><\/p>\n<h2 id=\"evolyuciya-asinhronnogo-koda\">Evoluci\u00f3n del c\u00f3digo as\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>La programaci\u00f3n as\u00edncrona, tal como la conocemos en JavaScript, solo puede ser implementada mediante funciones. Estas pueden ser pasadas como cualquier otra variable a otras funciones. As\u00ed nacieron los callbacks. Y esto es genial, divertido y entretenido, hasta que se convierte en tristeza, melancol\u00eda y pena. \u00bfPor qu\u00e9? Pues por algo simple:<\/p>\n<p><\/p>\n<ul>\n<li>Con el aumento de la complejidad del c\u00f3digo, el proyecto se convierte r\u00e1pidamente en bloques anidados dif\u00edciles de entender: el infierno de los callbacks.<\/li>\n<li>El manejo de errores se puede pasar por alto f\u00e1cilmente.<\/li>\n<li>No se pueden devolver expresiones con return.<\/li>\n<\/ul>\n<p><\/p>\n<p>Con la llegada de Promise, la situaci\u00f3n mejor\u00f3 un poco.<\/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>Se introdujeron cadenas de promesas, lo que mejor\u00f3 la legibilidad del c\u00f3digo.<\/li>\n<li>Apareci\u00f3 un m\u00e9todo separado para la captura de errores.<\/li>\n<li>Ahora hay una opci\u00f3n para la ejecuci\u00f3n paralela mediante Promise.all<\/li>\n<li>La asincron\u00eda anidada se puede resolver mediante async\/await<\/li>\n<\/ul>\n<p><\/p>\n<p>Pero las promesas tienen sus propias limitaciones. Por ejemplo, una promesa no se puede cancelar sin complicaciones, y lo m\u00e1s importante es que trabaja con un solo valor.<\/p>\n<p><\/p>\n<p>As\u00ed que hemos llegado suavemente a la programaci\u00f3n reactiva. \u00bfCansado? Bueno, puedes ir a preparar un t\u00e9, pensar un poco y regresar a seguir leyendo. Yo continuar\u00e9.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/48409ec625d57fec171214c1de332c85.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Programaci\u00f3n reactiva<\/strong>\u200a\u2014\u200auna paradigma de programaci\u00f3n enfocada en flujos de datos y en la propagaci\u00f3n de cambios. Vamos a analizar m\u00e1s a fondo qu\u00e9 es un flujo de datos.<\/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>Imaginemos que tenemos un campo de entrada. Creamos un array y en cada evento keyup del input guardaremos el evento en nuestro array. Me gustar\u00eda se\u00f1alar que nuestro array est\u00e1 ordenado por tiempo, es decir, el \u00edndice de los eventos m\u00e1s recientes es mayor que el \u00edndice de los m\u00e1s antiguos. Este array representa un modelo simplificado de un flujo de datos, pero todav\u00eda no es un flujo. Para que este array se pueda considerar un flujo, debe ser capaz de comunicar a los suscriptores que ha recibido nuevos datos. As\u00ed hemos llegado a la definici\u00f3n de un flujo.<\/p>\n<p><\/p>\n<h3 id=\"potok-dannyh\">Flujo de datos<\/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=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/68ec447abafb6b8a323b429ed94f8252.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Flujo\u200a<\/strong>\u2014\u200aes un array de datos ordenados por tiempo que puede informar sobre cambios en los datos. Ahora imagina lo conveniente que se vuelve escribir c\u00f3digo en el cual una acci\u00f3n requiere disparar varios eventos en diferentes partes del c\u00f3digo. Simplemente nos suscribimos al flujo y \u00e9l nos informar\u00e1 cu\u00e1ndo ocurren cambios. Y eso es lo que la biblioteca RxJs puede hacer.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/dcb1cfca8b4d8a887b63c302a7d6c06a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>RxJS <\/strong> \u2014 es una biblioteca para trabajar con programas as\u00edncronos y basados en eventos utilizando secuencias observables. La biblioteca proporciona un tipo b\u00e1sico <em>Observable<\/em>, varios tipos auxiliares (<em>Observer, Schedulers, Subjects<\/em>) y operadores para trabajar con eventos como colecciones (<em>map, filter, reduce, every<\/em> y similares de JavaScript Array).<\/p>\n<p><\/p>\n<p>Vamos a entender los conceptos b\u00e1sicos de esta biblioteca.<\/p>\n<p><\/p>\n<h3 id=\"observable-observer-producer\">Observable, Observer, Producer<\/h3>\n<p><\/p>\n<p>Observable \u2014 el primer tipo b\u00e1sico que vamos a revisar. Esta clase contiene la parte principal de la implementaci\u00f3n de RxJs. Est\u00e1 relacionada con el flujo observable, al cual se puede suscribir mediante el m\u00e9todo subscribe.<\/p>\n<p><\/p>\n<p>En Observable se implementa un mecanismo auxiliar para crear actualizaciones, conocido como <em>Observer<\/em>. La fuente de valores para el Observer se llama <em>Producer<\/em>. Puede ser un array, un iterador, un socket web, alg\u00fan evento, etc. As\u00ed que podemos decir que el observable act\u00faa como un intermediario entre Producer y Observer. <\/p>\n<p><\/p>\n<p>Observable maneja tres tipos de eventos del Observer:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 nuevos datos<\/li>\n<li>error \u2013 un error, si la secuencia se termina debido a una situaci\u00f3n excepcional. Este evento tambi\u00e9n implica el final de la secuencia.<\/li>\n<li>complete \u2014 una se\u00f1al de que la secuencia ha terminado. Esto significa que no habr\u00e1 m\u00e1s nuevos datos<\/li>\n<\/ul>\n<p><\/p>\n<p>Veamos una demostraci\u00f3n:<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/c5bcd2af0f18b6de3ab0dbc20db595d1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Al principio, procesaremos los valores 1, 2, 3, y despu\u00e9s de 1 segundo, obtendremos 4 y finalizaremos nuestro flujo.<\/p>\n<p>\n<b class=\"spoiler_title\">Pensando en voz alta<\/b><\/p>\n<p>Y aqu\u00ed me di cuenta de que era m\u00e1s interesante contar que escribir sobre esto. \ud83d\ude00 <\/p>\n<p><\/p>\n<h3 id=\"subscription\">Subscription<\/h3>\n<p><\/p>\n<p>Cuando nos suscribimos a un flujo, creamos una nueva clase <strong>subscription<\/strong>, que nos permite cancelar la suscripci\u00f3n mediante el m\u00e9todo <em>unsubscribe<\/em>. Tambi\u00e9n podemos agrupar suscripciones usando el m\u00e9todo <em>add<\/em>. Y, por supuesto, podemos desagrupar flujos usando <em>eliminar<\/em>. Los m\u00e9todos add y remove toman otra suscripci\u00f3n como entrada. Me gustar\u00eda destacar que cuando cancelamos una suscripci\u00f3n, estamos cancelando todas las suscripciones secundarias como si hubi\u00e9ramos llamado al m\u00e9todo unsubscribe en ellas. Sigamos.<\/p>\n<p><\/p>\n<h3 id=\"vidy-potokov\">Tipos de flujos<\/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>El Producer se crea fuera del observable<\/td>\n<td>El Producer se crea dentro del observable<\/td>\n<\/tr>\n<tr>\n<td>Los datos se transmiten en el momento de la creaci\u00f3n del observable<\/td>\n<td>Los datos se comunican en el momento de la suscripci\u00f3n<\/td>\n<\/tr>\n<tr>\n<td>Se necesita l\u00f3gica adicional para cancelar la suscripci\u00f3n<\/td>\n<td>El flujo se completa por s\u00ed mismo<\/td>\n<\/tr>\n<tr>\n<td>Utiliza una relaci\u00f3n uno a muchos<\/td>\n<td>Utiliza una relaci\u00f3n uno a uno<\/td>\n<\/tr>\n<tr>\n<td>Todas las suscripciones tienen un valor \u00fanico<\/td>\n<td>Las suscripciones son independientes<\/td>\n<\/tr>\n<tr>\n<td>Los datos se pueden perder si no hay suscripci\u00f3n<\/td>\n<td>Reemite todos los valores del flujo para una nueva suscripci\u00f3n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><\/p>\n<p>Si hiciera una analog\u00eda, representar\u00eda un flujo caliente como una pel\u00edcula en el cine. En el momento en que llegas, comienzas a verla desde ese punto. Un flujo fr\u00edo lo comparar\u00eda con una llamada al soporte t\u00e9cnico. Cualquiera que llame escucha la grabaci\u00f3n del contestador autom\u00e1tico de principio a fin, pero puedes colgar usando unsubscribe.<\/p>\n<p><\/p>\n<p>Me gustar\u00eda se\u00f1alar que tambi\u00e9n existen lo que se llaman flujos c\u00e1lidos (definici\u00f3n que he encontrado raramente y solo en comunidades extranjeras) \u2014 es un flujo que se transforma de un flujo fr\u00edo a uno caliente. Surge la pregunta: \u00bfd\u00f3nde usarlo?)) Dar\u00e9 un ejemplo pr\u00e1ctico.<\/p>\n<p><\/p>\n<p>Trabajo con Angular. Utiliza activamente RxJS. Para obtener datos del servidor, espero un flujo fr\u00edo y uso este flujo en la plantilla con asyncPipe. Si uso este pipe varias veces, volviendo a la definici\u00f3n del flujo fr\u00edo, cada pipe solicitar\u00e1 datos al servidor, lo cual, por decirlo suavemente, es extra\u00f1o. Pero si convierto el flujo fr\u00edo en uno c\u00e1lido, la solicitud se realizar\u00e1 una \u00fanica vez.<\/p>\n<p><\/p>\n<p>En general, entender los tipos de flujos es bastante complicado para los principiantes, pero es 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>Los operadores nos brindan la capacidad de trabajar con flujos. Ayudan a controlar los eventos que ocurren en un Observable. Vamos a revisar un par de los m\u00e1s populares, y se puede encontrar m\u00e1s informaci\u00f3n sobre los operadores en los enlaces de informaci\u00f3n \u00fatil.<\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 of<\/strong><\/p>\n<p><\/p>\n<p>Comencemos con el operador auxiliar of. Crea un Observable a partir de un valor simple.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/68f382447e306392b025867a9a1e88e7.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 filter<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/24ac65fdb5ccc7f6301b3dfe49f1e804.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>El operador de filtrado filter, como se puede entender por su nombre, filtra la se\u00f1al del flujo. Si el operador devuelve verdadero, permite que contin\u00fae.<\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 take<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/b3e7a2a2e03038d6fc250247ff4496a2.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>take \u2014 Acepta el n\u00famero de emisiones, despu\u00e9s de las cuales finaliza el flujo.<\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 debounceTime<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/add686e546a0b6169c38fb3b457da928.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>debounceTime \u2014 descarta los valores emitidos que ocurren en el intervalo de tiempo especificado entre las salidas; tras el transcurso del intervalo de tiempo, emite el \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  \/\/ Emitir valor cada 1000ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n\n  \/\/ Emitir valor cada 1500ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1500);\n}).pipe(\n  debounceTime(700),  \/\/ Esperar 700ms antes de procesar el valor\n  take(3)\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/dbb690d6fea6c43c1f0a2bdabea57934.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 takeWhile<\/strong><\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/120d9fe6ddf5a60ddffc8742989b27ff.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Emite valores hasta que takeWhile devuelva falso, despu\u00e9s de lo cual se desuscribe del flujo.<\/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 un valor cada 1000 ms\n  setInterval(() =&gt; {\n    observer.next(i++)\n  }, 1000);\n}).pipe(\n  takeWhile( producer =&gt;  producer &lt; 5 )\n);  <\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/d2910d1bf9fab228acc9241fdbad3d4a.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 combineLatest<\/strong><\/p>\n<p><\/p>\n<p>El operador combinado combineLatest se asemeja a promise.all. Combina m\u00faltiples flujos en uno. Una vez que cada flujo emite al menos una vez, obtenemos los \u00faltimos valores de cada uno como un array. Luego, despu\u00e9s de cualquier emisi\u00f3n de los flujos combinados, comenzar\u00e1 a devolver nuevos valores.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/c39bc0a8a736ed30ad147055110bbf55.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { combineLatest, Observable } = Rx;\nconst { take } = RxOperators;\n\nconst observer_1 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emite un valor cada 1000 ms\n  setInterval(() =&gt; {\n    observer.next('a: ' + i++);\n  }, 1000);\n});\n\nconst observer_2 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emite un valor cada 750 ms\n  setInterval(() =&gt; {\n    observer.next('b: ' + i++);\n  }, 750);\n});\n\ncombineLatest(observer_1, observer_2).pipe(take(5));<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/7fc35461f446987ef81302ff7c2ed5a8.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 zip<\/strong><\/p>\n<p><\/p>\n<p>Zip espera un valor de cada flujo y forma un array basado en esos valores. Si un valor no llega de alg\u00fan flujo, el grupo no ser\u00e1 formado.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/0be5ee0d2ec56bd2bc245b15d43d4cc1.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { zip, Observable } = Rx;\nconst { take } = RxOperators;\n\nconst observer_1 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emite un valor cada 1000 ms\n  setInterval(() =&gt; {\n    observer.next('a: ' + i++);\n  }, 1000);\n});\n\nconst observer_2 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emite un valor cada 750 ms\n  setInterval(() =&gt; {\n    observer.next('b: ' + i++);\n  }, 750);\n});\n\nconst observer_3 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emite un valor cada 500 ms\n  setInterval(() =&gt; {\n    observer.next('c: ' + i++);\n  }, 500);\n});\n\nzip(observer_1, observer_2, observer_3).pipe(take(5));<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/e2606bf8ea5f8a660699ebe896a27d80.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 forkJoin<\/strong><\/p>\n<p><\/p>\n<p>forkJoin tambi\u00e9n combina flujos, pero emite un valor solo cuando todos los flujos se han completado.<\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/6c430d7eeafbc8a7c1c228ddfe0e44b5.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { forkJoin, Observable } = Rx;\nconst { take } = RxOperators;\n\nconst observer_1 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emite un valor cada 1000 ms\n  setInterval(() =&gt; {\n    observer.next('a: ' + i++);\n  }, 1000);\n}).pipe(take(3));\n\nconst observer_2 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emite un valor cada 750 ms\n  setInterval(() =&gt; {\n    observer.next('b: ' + i++);\n  }, 750);\n}).pipe(take(5));\n\nconst observer_3 = Observable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emite un valor cada 500 ms\n  setInterval(() =&gt; {\n    observer.next('c: ' + i++);\n  }, 500);\n}).pipe(take(4));\n\nforkJoin(observer_1, observer_2, observer_3);<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/df110efc7ece46fc1d8da2d7693f75bb.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operadores \u2014 map<\/strong><\/p>\n<p><\/p>\n<p>El operador de transformaci\u00f3n map convierte el valor emitido en uno nuevo. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/2196ff9f82dd7aaeb00ab76475176d32.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<pre><code class=\"javascript\">const { Observable } = Rx;\nconst { take, map } = RxOperators;\n\nObservable.create((observer) =&gt; {\n  let i = 1;\n  \/\/ Emite un valor cada 1000 ms\n  setInterval(() =&gt; {\n    observer.next(i++);\n  }, 1000);\n}).pipe(\n  map(x =&gt; x * 10),\n  take(3)\n);\n<\/code><\/pre>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/4e4ff3e2eb4acf69f16559c711a2e666.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p><strong>Operadores \u2013 share, tap<\/strong><\/p>\n<p><\/p>\n<p>El operador tap \u2014 permite realizar efectos secundarios, es decir, acciones que no afectan la secuencia.<\/p>\n<p><\/p>\n<p>El operador utilitario share puede convertir un flujo fr\u00edo en uno caliente. <\/p>\n<p><\/p>\n<p><img decoding=\"async\" alt=\"Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs )\" src=\"\/wp-content\/uploads\/2019\/08\/c46e96420ed78d197ceef829ff74c82d.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Hemos terminado con los operadores. Pasemos al Subject.<\/p>\n<p>\n<b class=\"spoiler_title\">Pensando en voz alta<\/b><\/p>\n<p>Y aqu\u00ed fui a tomarme un t\u00e9. Me han cansado estos ejemplos \ud83d\ude00<\/p>\n<p><\/p>\n<h2 id=\"semeystvo-subject-ov\">Familia de subjects<\/h2>\n<p><\/p>\n<p>La familia de subjects es un claro ejemplo de flujos calientes. Estas clases son una especie de h\u00edbrido que act\u00faa simult\u00e1neamente como observable y observer. Dado que el subject es un flujo caliente, es necesario desuscribirse de \u00e9l. Los m\u00e9todos principales son:<\/p>\n<p><\/p>\n<ul>\n<li>next \u2013 transmisi\u00f3n de nuevos datos al flujo<\/li>\n<li>error \u2013 error y finalizaci\u00f3n del flujo<\/li>\n<li>complete \u2013 finalizaci\u00f3n del flujo<\/li>\n<li>subscribe \u2013 suscribirse al flujo<\/li>\n<li>unsubscribe \u2013 desuscribirse del flujo<\/li>\n<li>asObservable \u2013 transformarlo en un observador<\/li>\n<li>toPromise \u2013 lo transforma en una promesa<\/li>\n<\/ul>\n<p><\/p>\n<p>Se identifican 4 o 5 tipos de subjects. <\/p>\n<p>\n<b class=\"spoiler_title\">Pensando en voz alta<\/b><\/p>\n<p>En la transmisi\u00f3n habl\u00e9 de 4, y result\u00f3 que han agregado uno m\u00e1s. Como se dice, vive y aprende.<\/p>\n<p><\/p>\n<p>Subject simple <code>new Subject()<\/code>es el tipo m\u00e1s simple de subjects. Se crea sin par\u00e1metros. Solo transmite valores que llegan despu\u00e9s de la suscripci\u00f3n.<\/p>\n<p><\/p>\n<p>BehaviorSubject <code>new BehaviorSubject(defaultData)<\/code> es, en mi opini\u00f3n, el tipo de subject m\u00e1s com\u00fan. Acepta un valor por defecto. Siempre guarda los datos del \u00faltimo emitido, que se transmite en la suscripci\u00f3n. Esta clase tambi\u00e9n tiene un m\u00e9todo \u00fatil, value, que devuelve el valor actual del flujo.<\/p>\n<p><\/p>\n<p>ReplaySubject <code>new ReplaySubject(bufferSize?: number, windowTime?: number)<\/code> Puede aceptar opcionalmente como primer argumento el tama\u00f1o del b\u00fafer de valores que almacenar\u00e1 y como segundo el tiempo durante el cual necesitamos las modificaciones.<\/p>\n<p><\/p>\n<p>AsyncSubject <code>new AsyncSubject()<\/code> al suscribirse no ocurre nada y el valor se devolver\u00e1 solo al completo. Solo se devolver\u00e1 el \u00faltimo valor del flujo.<\/p>\n<p><\/p>\n<p>WebSocketSubject <code>new WebSocketSubject(urlConfigOrSource: string | WebSocketSubjectConfig | Observable, destination?: Observer)<\/code> la documentaci\u00f3n no dice nada al respecto y yo lo veo por primera vez. Quien sepa qu\u00e9 hace, escriba y lo complementamos.<\/p>\n<p><\/p>\n<p>Uf. Bueno, hemos revisado todo lo que quer\u00eda contar hoy. Espero que esta informaci\u00f3n haya sido \u00fatil. Puedes revisar la bibliograf\u00eda en la pesta\u00f1a de informaci\u00f3n \u00fatil.<\/p>\n<p><\/p>\n<h2 id=\"poleznaya-informaciya\">Informaci\u00f3n \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> \u2014 enlace a la transmisi\u00f3n<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/ruvds\/blog\/337042\/\">https:\/\/habr.com\/ru\/company\/ruvds\/blog\/337042\/<\/a><\/noindex> \u2014 C\u00f3mo funciona JS: revisi\u00f3n del motor, mecanismos de ejecuci\u00f3n, pila de llamadas<\/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 C\u00f3mo funciona JS: el ciclo de eventos, la asincron\u00eda y cinco formas de mejorar el c\u00f3digo 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 C\u00f3mo funciona el Event Loop en JavaScript<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/tproger.ru\/translations\/asynchronous-javascript\/\">https:\/\/tproger.ru\/translations\/asynchronous-javascript\/<\/a><\/noindex> \u2014 La evoluci\u00f3n de JavaScript as\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 Qu\u00e9 es RxJS y por qu\u00e9 es \u00fatil conocerlo<\/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 Aplicaciones pr\u00e1cticas de RxJS<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/coursetro.com\/posts\/code\/148\/RxJS-Observables-Tutorial---Creating-&amp;-Subscribing-to-Observables\">https:\/\/coursetro.com\/posts\/code\/148\/RxJS-Observables-Tutorial&#8212;Creating-&amp;-Subscribing-to-Observables<\/a><\/noindex> \u2014 Tutorial de RxJS Observables \u2014 Creaci\u00f3n y suscripci\u00f3n a Observables<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/slides.com\/zenabsaleem\/rxjs-hot-cold-observables#\/\">https:\/\/slides.com\/zenabsaleem\/rxjs-hot-cold-observables#\/<\/a><\/noindex> \u2014 RXJS: Observables Fr\u00edos y Calientes<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/clck.ru\/FiPgB\">https:\/\/clck.ru\/FiPgB<\/a><\/noindex> \u2014 Clases, funciones para crear Observable. Operadores.<\/li>\n<li><noindex><a rel=\"nofollow\" href=\"https:\/\/www.learnrxjs.io\/operators\/\">https:\/\/www.learnrxjs.io\/operators\/<\/a><\/noindex> \u2014 Operadores de RxJS por ejemplo<\/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 Variedades de Subject y Programaciones en RxJS<\/li>\n<\/ul>\n<p>Fuente: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/462355\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u041e\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u043a\u0438\u0439 \u0421\u0435\u0440\u0433\u0435\u0439. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0432\u0435\u043b \u0441\u0442\u0440\u0438\u043c \u043f\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0432 JavaScript. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u043a\u043e\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b. \u041d\u043e \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0432\u043e\u0434\u043d\u0443\u044e. \u0418\u0442\u0430\u043a, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0439: \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u0441\u0442\u0435\u043a \u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u044c? \u0421\u0442\u0435\u043a \u2014 \u044d\u0442\u043e \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f, \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043a\u043e\u0442\u043e\u0440\u043e\u0439 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27545,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-36774","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442. \u041d\u0430 \u0441\u0432\u044f\u0437\u0438 \u041e\u043c\u0435\u043b\u044c\u043d\u0438\u0446\u043a\u0438\u0439 \u0421\u0435\u0440\u0433\u0435\u0439. \u041d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u044f \u0432\u0435\u043b \u0441\u0442\u0440\u0438\u043c \u043f\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c\u0443 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044e, \u0433\u0434\u0435 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u043b \u043f\u0440\u043e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u044c \u0432 JavaScript. \u0421\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u0431\u044b \u0445\u043e\u0442\u0435\u043b \u0437\u0430\u043a\u043e\u043d\u0441\u043f\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/es\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"es_ES\" \/>\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\/es\/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\udd47Programaci\u00f3n as\u00edncrona en JavaScript. ( Callback, Promise, RxJs ) | ProHoster","description":"Hola a todos. Soy Sergey Omelnitsky. No hace mucho, realic\u00e9 una transmisi\u00f3n en vivo sobre programaci\u00f3n reactiva, donde habl\u00e9 sobre la asincron\u00eda en JavaScript. Hoy me gustar\u00eda resumir este material.","canonical_url":"https:\/\/prohoster.info\/es\/blog\/news\/asinhronnoe-programmirovanie-v-javascript-callback-promise-rxjs","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"es_ES","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\/es\/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\/es\/wp-json\/wp\/v2\/posts\/36774","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/comments?post=36774"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/posts\/36774\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media\/27545"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/media?parent=36774"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/categories?post=36774"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/es\/wp-json\/wp\/v2\/tags?post=36774"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}