Vuelta a los fundamentos

Rate this content
Bookmark

“Nunca creerás de dónde vienen los objetos en JavaScript.”


“Estos 10 lenguajes son peores que JavaScript en programación asíncrona.”


Exploraremos algunos aspectos de JavaScript que podrías dar por sentado en el taller más sensacionalista de nodecongress.com.


Para asistir a este taller solo necesitas ser capaz de escribir y ejecutar código NodeJS en tu computadora. Tanto desarrolladores junior como senior son bienvenidos.


Los objetos son de Marte, las funciones son de Venus


Sumergámonos en los entresijos de los objetos y luego ampliemos nuestra perspectiva para ver los módulos desde un punto de vista diferente. ¿Cuántas formas hay de crear objetos? ¿Son realmente útiles? ¿Cuándo deberías considerar usarlos?


Si ahora estás pensando `¿a quién le importa?`, entonces este taller es probablemente para ti.


JavaScript asíncrono: ¿las partes buenas?


Tengamos una conversación honesta.


Quiero decir... ¿por qué, oh por qué, tenemos que lidiar con todo esto? Supongo que también depende de la perspectiva. Primero asumamos una verdad incómoda al respecto: podría ser peor... luego tal vez podamos empezar a ver las características no tan malas, incluso geniales, de JavaScript en relación a los programas no bloqueantes.

128 min
15 Feb, 2022

Comments

Sign in or register to post your comment.

Video Summary and Transcription

Este taller cubre los principios básicos y patrones en el desarrollo y la ingeniería de software. Explora temas como objetos, funciones, cadenas de prototipos, clases, módulos y programación asíncrona en JavaScript. El taller enfatiza la importancia de comprender el contexto, la encapsulación y el uso de promesas para gestionar el comportamiento asíncrono. También discute las diferencias entre la ejecución de código sincrónico y asíncrono y proporciona ideas sobre los patrones de diseño y las mejores prácticas para escribir código eficiente y mantenible.`, `seotitle`: null, `seodescription`: nul

Available in English

1. Introducción al Masterclass

Short description:

Gracias por unirte a este masterclass sobre principios y patrones básicos. Creo que son la mejor inversión en tu formación. Hoy nos centraremos en dos temas: objetos y el comportamiento asíncrono de Node.js.

Así que creo que podemos empezar ahora, una vez más, mi nombre es Guillermo y soy tu anfitrión hoy. Gracias por unirte a este masterclass y un agradecimiento especial por venir porque sé que este no es el tema más llamativo. Los principios básicos y patterns no son un marco elegante que todos estén usando o cosas así. Así que, sí, bien por ustedes, supongo. Sí, habrá una grabación de esta sesión y creo que la organización la pondrá donde puedas acceder a ella. Sí. Ahí lo tienes. Genial. Entonces, una vez más, mi nombre es Guillermo. Soy un desarrollador de software, probablemente como la mayoría de ustedes. Trabajo en la empresa llamada DnSimple como ingeniero de software. Normalmente trabajo con Ruby. Pero también trabajo mucho con JavaScript y en el pasado también he trabajado en bases de código de Java. En DnSimple, somos un equipo pequeño. Y, por cierto, estamos buscando personas para unirse a nosotros. Así que asegúrate de visitar nuestra página de empleos Si estás en el mercado laboral, estaremos encantados de saber de ti. Entonces, este masterclass se trata de lo básico, ¿verdad? Y realmente lo digo en serio cuando pongo ese título. Porque cuando doy charlas y entrenamientos como este, siempre trato de simplificarlo a principios básicos y patterns. Porque eso es lo que realmente creo que es la mejor inversión que cualquiera puede hacer en su formación. Porque ya sabes, los frameworks y las bibliotecas tienden a cambiar mucho, son muy volátiles, mientras que los principios básicos y patterns son cosas que han existido durante mucho, mucho tiempo, y se ha demostrado que son valiosos y útiles a lo largo del tiempo. Así que ahí lo tienes. Básicamente así es como trato de pensarlo. Y también, en un masterclass remoto de dos horas como este, no hay mucho espacio para hablar de muchas cosas y profundizar mucho. Por eso quería centrarme solo en dos temas, uno objetos y dos el comportamiento asíncrono de Node.js porque creo que son temas con los que la mayoría de las personas que conozco luchan y estos son también cosas que damos por sentado sin realmente tener mucho tiempo para pensar en ello.

2. Understanding Objects and Values in JavaScript

Short description:

No se proporcionarán notas prácticas. Nos centraremos en el código durante las próximas dos horas. Los objetos son colecciones de pares clave-valor en JavaScript. Los valores pueden ser cualquier cosa que coloques a la derecha de un signo igual. Veamos un ejemplo con la variable foo y la propiedad A. Podemos acceder a la propiedad A utilizando la notación de punto o la notación de corchetes. Ambas devolverán el valor 44.

Entenderlos y razonar sobre ellos y realmente conocer cómo funcionan. Así que vayamos al grano. ¿Alguien pregunta si se van a proporcionar notas prácticas? No, lo siento, no he preparado ninguna nota práctica para ustedes. Se trata simplemente de lidiar con el código que vamos a ver durante las próximas dos horas y, por supuesto, el repositorio estará allí, es público y pueden hacer lo que quieran con él después. Entonces, una vez más, estos son temas sutiles que requieren mucho tiempo para entrar en detalles, etcétera. Y lo que voy a decir durante las próximas dos horas, deben entender que son solo modelos mentales, heurísticas, formas de pensar en las cosas, no descripciones canónicas de cómo son las cosas en el lenguaje, ¿de acuerdo? Entonces, comencemos con los objetos. El primer tema fue que los objetos son de Marte, las funciones son de Venus. Esto fue una especie de broma tonta. Pero, en realidad, ¿qué es un objeto y por qué debería importarme? Esa es precisamente la pregunta que intentaré responder. Y la cosa es que la forma en que pienso en los objetos es como si fueran valores que tienen esta forma de una colección de pares clave valor. Entonces, en JavaScript, las claves de esos objetos se llaman propiedades. Y los valores, un valor, ¿verdad? Así que, oh. Vale. Voy a habilitar esto. No sé si va a funcionar. Así que, transcripción en vivo. Ahí lo tienen. Funciona. De acuerdo. Sigamos. Entonces, ¿qué es un valor, ¿verdad? Cualquier cosa que puedas colocar a la derecha de un signo igual, eso es un valor en JavaScript. Y descubrirás que casi cualquier cosa es un valor. En realidad, puedes colocar cualquier cosa que quieras a la derecha de un signo igual. Estuve intentando mucho pensar en algo que no fuera un valor, pero no encontré nada. Así que, pasemos a la primera que tengo para ustedes, tenemos un par de carpetas. Una se llama objetos y la otra se llama a sink. Así que, tomemos el archivo part1.js. Y encontrarán tres líneas aquí. Y esto muestra cómo se puede pensar en un objeto como una colección de pares clave-valor. ¿De acuerdo? En la primera línea aquí estamos creando una variable llamada foo. Y a la derecha del signo igual , quiero decir, esta parte del signo igual, tenemos una llave de apertura y luego una A que es el nombre de la propiedad. Luego dos puntos y luego 44 que es el valor que estoy asignando a llamar A. Esto es un objeto, justo ahí. Y sí. Solo tiene una propiedad con solo el valor. Y sé que estamos hablando de cosas muy simples, pero esto crecerá sobre todo lo que introduzcamos. ¿De acuerdo? Así que necesitamos establecer los conceptos básicos, ¿de acuerdo? Esto es lo que estamos haciendo ahora mismo. Y la forma en que podemos hacer referencia a la propiedad A en foo es utilizando la notación de punto o la notación de corchetes. Y tienen un ejemplo de eso en las líneas siguientes. La primera línea aquí, console.log, foo.A, esto es una notación de punto. Y la siguiente línea utiliza la notación de corchetes, donde tienes foo, corchete cuadrado. Ups, perdón, moviendo eso. Corchete cuadrado. Y luego el nombre de la propiedad como una cadena. Y eso te dará 44 en ambos casos. Entonces, la forma en que funciona CodeSandbox es que tienes en la esquina inferior derecha, una sección con la pestaña de terminal, la pestaña de consola y la pestaña de problemas Y tienes un signo más muy pequeño en el borde derecho que puedes hacer clic. Y eso debería abrirte una nueva terminal. Y voy a habilitar eso para todos ustedes que me están siguiendo aquí. Entonces, si creas una terminal, básicamente es un indicador donde puedes ejecutar cosas.

3. Objetos y Funciones en JavaScript

Short description:

Los objetos son colecciones de pares clave-valor. Las funciones pueden asignarse como valores de una propiedad. Llamar a una función por su nombre y ejecutarla con paréntesis es diferente de llamar a una función como propiedad de un objeto. La ejecución del código produce la salida esperada.

Y no estoy seguro si están viendo esto, pero estoy escribiendo objetos de nodo slash parte uno. Oh, Tengo mi teclado en español. Así que, vamos a cambiar eso. Objetos, y luego presiono enter. Y ahí lo tienen. Oh, por cierto, les di permisos de edición para cambiar eso, así que por favor, intenten no cambiar las cosas. Si accidentalmente cambian algo, avísenme en el chat y lo restauraré. Pero básicamente estamos compartiendo los mismos archivos, así que por favor no cambien las cosas. Porque de lo contrario, no podrán crear la terminal a la derecha. Entonces, nuevamente, si abren una terminal, y vamos a usar esto mucho durante la masterclass, pueden ejecutar este archivo que estamos editando aquí, el archivo part1.js. Entonces, ¿alguien puede confirmar que pudo abrir una terminal y ejecutar esto en su sesión de CodeSandbox, por favor, para mí? De acuerdo. Un par de confirmaciones más, por favor, para que pueda continuar . Creé una terminal, pero en realidad no puedo escribir ningún código, así que no puedo confirmar. Pero veo una pantalla, así que para mí es un buen comienzo, y tal vez más tarde lo arreglaré. Durante algunos ensayos, algunas personas que intentaron esto tuvieron el mismo problema y refrescaron la pantalla y comenzó a funcionarles. Así que tal vez puedan intentar eso también. Pero sí, si me siguen en la pantalla y ven lo que hice aquí, verán que ejecuté el script y obtuve las dos líneas de consola local de las líneas tres y cuatro, y obtuve lo que esperábamos, ¿verdad? Obtuve Foo.a igual a 44, y Foo sqrt corchete de a igual a 44. Así que refrescar funciona. Increíble. Esto funciona. No estaba seguro de que tal vez con 60 personas, no sé, dejaría de funcionar o algo así, pero estoy feliz de ver eso. Sí, confirmo que refrescar soluciona, y pude crear nuevamente la terminal. Funciona. Gracias. Gracias. Increíble. Esto funciona. De acuerdo, genial. Así que continuemos, ¿verdad? Voy a hacer esto más grande para nosotros. Genial. Entonces hemos visto que los objetos son colecciones de pares clave-valor. Las claves se llaman propiedades, y casi cualquier cosa puede ser un valor. A continuación, lo que voy a hacer es eliminar este comentario aquí para que ahora el archivo se ejecute hasta la línea 21, en este caso. Genial. Entonces, lo que estamos viendo aquí es que las funciones también son valores. Como, pueden asignarse como valores de una propiedad. Para mostrar eso, estoy creando aquí una función completa que creará alguna constante y alguna llamada de consola aquí. Y luego estoy creando un objeto bar que tiene una propiedad B, y luego este objeto bar tiene una propiedad completa. Y su valor es la función que creé en la línea 8. ¿Ven eso? Que está haciendo referencia a esta función aquí. Y ahora, lo que estoy haciendo en las líneas 18 y 19 es básicamente llamar a lo que es la misma función de dos formas diferentes. Y esto es importante que entendamos lo diferentes que son estas formas de llamar a la función de forma aislada. Como estoy haciendo aquí. Solo estoy, ya sabes, tomando el nombre de la función. Y usando algunos paréntesis aquí para ejecutar esa función. Esto es diferente a hacer esto donde ejecuto la función completa como propiedad del objeto bar. Lo que se mantiene o se almacena en la propiedad completa. ¿De acuerdo? Entonces ejecutemos esto en la terminal, nodo objetos slash parte 1, oh, no, no, parte 1, disculpen. Y luego lo que obtuvimos, voy a copiar esto en el chat. Entonces, lo que obtuvimos son las primeras dos

4. Entendiendo el Contexto de las Funciones en JavaScript

Short description:

La consola imprime los valores A, B y C. El primer console log en la línea 18 imprime undefined, mientras que el segundo console log en la línea 19 imprime 33. Las funciones tienen un contexto de ejecución, representado por la palabra clave 'this'. El contexto puede variar dependiendo de cómo se llame a la función. Se pueden utilizar diferentes métodos como call, apply y bind para establecer el contexto. Al llamar a una función como propiedad de un objeto, 'this' se refiere al objeto en sí mismo.

líneas del experimento anterior y luego dos líneas nuevas. Y aquí necesitamos echar un vistazo a lo que hace el console log aquí. El console log imprimirá un valor llamado A, que estamos definiendo en la línea 6. Luego imprime this dot B, lo que sea que sea. Aún no hemos explicado qué es esto realmente, pero por ahora lo hace. Y luego C, que está declarando la misma función. El valor de A y C, creo que es fácil de vincular, ya sabes, que esto va a ser 1 y esto va a ser C. Es probablemente fácil de ver. Es más difícil ver qué va a ser esto aquí. Entonces, el primer console log que corresponde a la línea 18 imprime undefined. Y el segundo console log, correspondiente a la línea 19, imprime 33. Y esto es porque this, por alguna razón, cuando llamo a la función como propiedad del objeto bar , entiende que this es en realidad el objeto bar. Entonces, cuando hace referencia a la propiedad b en this, va a tomar este aquí, b igual a 33. Por otro lado, cuando ejecuto la función de forma aislada, la función no sabe nada sobre this dot B, y por eso obtengo undefined. Entonces, la conclusión aquí es que las funciones tienen lo que llamamos un contexto de ejecución, y ese contexto es básicamente el valor de this, que es un nombre especial. Cuando llamas a esto en una función, puede significar cosas diferentes, dependiendo del contexto de ejecución de esa función. Cuando llamas a la función de forma aislada, como hice aquí, this corresponderá al objeto global. Y cuando llamas a la función como propiedad de un objeto, como hice aquí, this se convertirá en el objeto mismo. Y podemos comprobarlo declarando aquí un valor para B. Y ahora que he guardado, si ejecuto el script de nuevo, oh, bueno, no importa. No te preocupes. Ejecutemos el siguiente ejemplo para ver la configuración del contexto. Además, otra forma de establecer el contexto es bind, pero ahí lo tienes. Sí, hay diferentes formas de establecer el contexto utilizando los diferentes métodos en los objetos de funciones. Solo estoy usando call y veremos que hay otros como apply o bind, etc. Así que echemos un vistazo a estas dos líneas aquí, línea 21 y 22. Lo que estoy haciendo aquí es, bueno, en primer lugar, tal vez algunos de ustedes estén sorprendidos de ver que puedo hacer referencia a una propiedad llamada call en una función completa. Tal vez no esperaban que las funciones sean en realidad objetos que también tienen propiedades. Eso tal vez sea lo primero que les resulte nuevo. Y sí, las funciones son objetos en JavaScript. Entonces tienen propiedades que se pueden usar y métodos, etc. Entonces, cuando usas el nombre de la función.call, básicamente estás expresando que necesitas ejecutar la función. Y el método call aquí tiene el primer argumento y este primer argumento es lo que es el valor de this, básicamente le estás diciendo al motor de JavaScript que this es igual a un objeto con B igual a 22 en este caso. Entonces, si ejecuto esto, ahí lo tienes, vemos que este B se convierte en 22. Ahora. Y dado que la propiedad full en bar también es la misma función, también puedes usar dot call en ella y luego hacer lo mismo nuevamente. Y luego puedes pasar un contexto completamente diferente también. Como puedes ver, métodos como call te permiten establecer un valor específico para this. Hay otros como alguien en el chat sugirió que puedes usar.bind. Voy a copiar su ejemplo. Ahí lo tienes. Y también puedes usar la función completa apply y luego algo aquí. Y todas estas cosas funcionan. Y finalmente, tengo este último ejemplo aquí. Espero que puedas ver lo que estoy haciendo aquí. Que estoy llamando a la función con el mismo objeto como contexto, lo cual es redundante. Esto es básicamente lo mismo que hacer esto. Entonces, nuevamente, esta forma de llamar a las funciones, no sé cómo llamarla. No sé si incluso tiene un nombre. Pero esta forma de llamar a las funciones cuando son parte de un objeto, esto está llamando a la ejecución.

5. Ejecutando Funciones en JavaScript

Short description:

Estas dos formas de ejecutar funciones en JavaScript son perfectamente válidas para la mayoría de los escenarios. Si te encuentras usando call, apply, bind, etc., con frecuencia, puede valer la pena revisar tu enfoque. Es importante evitar código innecesariamente complicado y luchar contra el lenguaje.

asegurando la función como un método del objeto. Como un método, como lo que comúnmente entendemos como un método de objeto. Y la diferencia es que esto se convertirá en el objeto mismo. Esa es la idea principal aquí. Y otra nota sobre esto es que estas dos formas de ejecutar funciones en JavaScript son perfectamente válidas para la mayoría de los escenarios que encontrarás. Si te encuentras llamando a call, apply, bind, etc., con frecuencia en algún proyecto, tal vez sería bueno retroceder y echar un vistazo y revisar esto en caso de que estés haciendo las cosas de una manera demasiado complicada o tal vez estés luchando. Casi se siente como si estuvieras luchando contra el lenguaje en este caso, así que sí, algo para pensar.

6. Comprendiendo las Cadenas de Prototipos en JavaScript

Short description:

Los objetos son colecciones de pares clave-valor. Al utilizar paréntesis después de hacer referencia a propiedades en un objeto, la función se ejecuta como un método del objeto. JavaScript conoce el valor de las propiedades a través de la cadena de prototipos, que comienza en la propiedad __proto__. Todas las cadenas de prototipos terminan con un valor nulo y el prototipo anterior es un objeto vacío. JavaScript buscará en la cadena de prototipos hasta que encuentre la propiedad o devuelva undefined. Las propiedades pueden ser heredadas a través de la cadena de prototipos.

si estás haciendo esto con frecuencia. Así que permíteme revisar mis notas rápidamente. Como resumen, ¿verdad? Primero, los objetos pueden considerarse como colecciones de pares clave valor, las claves se llaman propiedades y cualquier cosa puede ser un valor realmente. Y luego cuando usas paréntesis, como aquí, después de hacer referencia a algunas propiedades en un objeto, vas a ejecutar esa función como un método del objeto. Entonces esto se convierte en algo más. Esto se convierte en el objeto. Ahora que conocemos la estructura de los objetos y cómo hacer referencia a las propiedades, la siguiente pregunta que debemos poder responder es cómo funciona la referencia a las propiedades, y para responder eso, como, ¿por qué JavaScript sabe que a es igual a 44 cuando hago esto, ¿verdad? Y por qué sabe acerca de otras propiedades como esta, ¿verdad? A.toString. No describí una propiedad toString por completo. Lo siento. Esto no es a. Mi intención era que fuera completo realmente. Así que no estoy describiendo No estoy creando una propiedad toString por completo. Entonces, ¿por qué funciona esto? Y para responder eso, necesitamos comenzar a mirar el prototipo. Entonces JavaScript es un lenguaje orientado a objetos que se basa, como, se basa en prototipos. No se basa en clases, realmente. En herencia prototípica, ¿verdad? Y la forma en que esto funciona es que cada objeto tiene una cadena de prototipos. Y esa cadena de prototipos comienza en la propiedad __proto__. Esta es una propiedad especial que todos los objetos tienen. Casi todos los objetos tienen. Oh, mierda. Estoy Así que vamos a eliminar todo esto y ejecutar este ejemplo aquí. Voy a eliminar todos los registros de la consola aquí para limpiar las salidas. Genial. Entonces este método console.beer nos mostrará la estructura general de los objetos como aquí estoy viendo aquí. Este es un objeto vacío. no hay realmente nada que mostrar sobre este objeto. Solo un par de llaves vacías. Pero luego el siguiente paso, como esta sería la propiedad en este objeto que inicia la cadena de prototipos, vemos esta salida aquí. Y aquí estamos viendo que este es un objeto con un prototipo nulo que proporciona algunos métodos, por ejemplo, o algunas propiedades, por ejemplo, la propiedad Constructor, la propiedad ToString, valor de etc. Y en sí mismo tiene otra propiedad con su siguiente, ya sabes, paso cadena de prototipos. Y luego la última línea aquí, el prototipo del prototipo, es solo un valor nulo. Entonces lo primero que hay que notar aquí es que todas las cadenas de prototipos terminarán con los mismos dos pasos. El último paso siempre es un objeto nulo, o lo siento, un valor nulo, y luego el valor anterior, el prototipo anterior es un objeto vacío. Y esa es la razón por la que cuando hago foo.toString, esto funciona, porque toString no está definido en el objeto en sí, está definido en el primer paso en la cadena de prototipos. Y JavaScript intentará realmente no devolverte undefined. Buscará en toda la cadena de prototipos hasta que llegue a null. Y luego sí, devuelve un undefined, porque si en este paso aquí, no encuentra tu propiedad, entonces no está bien. Básicamente, así es como funciona. Veamos el gráfico rápidamente. Además, otro. Sí. O un objeto con un prototipo de bar. Sí, ahí lo tienes. Genial. Entonces el prototipo se trata de una cadena que comienza en esta propiedad aquí, __proto__. Y siempre termina en un valor nulo, y luego el paso anterior siempre es un objeto vacío. Y es por eso que tenemos algunas propiedades que no tenemos que definir cada vez que se heredan. Y quiero decir, qué en aquí se heredan, eh, porque algún paso en la cadena de prototipos las tiene. Y luego JavaScript usará eso en lugar de, simplemente, ya sabes, mirar el objeto y decir, no, está en el teléfono. No, no. Un paso en la cadena de prototipos tiene eso.

7. Introducción a la Herencia y las Clases

Short description:

Entonces usaremos eso por ahora. Esta es una forma realmente complicada de hacer herencia. Hagamos un pequeño experimento. Si intentamos imprimir en pantalla la propiedad a del objeto bar, será undefined. Y también sabemos que la propiedad A no es proporcionada por nadie en la cadena de prototipos de este objeto. Y lo que estamos haciendo aquí es usar foo como el prototipo o el primer paso en la cadena de prototipos del objeto bar. Y luego, si hacemos lo mismo nuevamente, ya que foo ahora proporciona un valor para A, esto dejará de ser undefined. Ahora hablemos un poco sobre las clases. Las clases no existen en JavaScript. Tenemos la capacidad de describir clases porque hay una sintaxis para ello, pero es solo sintaxis. También hay algunas verificaciones de seguridad en su lugar si usas clases, y por eso terminaremos usándolas. Para entender por qué tenemos clases hoy en día, primero debemos retroceder en el tiempo y hacer cosas como solíamos hacer cuando no había sintaxis de clase en el lenguaje. Consideremos el segundo archivo aquí, part2.js. Aquí puedes ver las cosas que teníamos que hacer antes de que hubiera clases en el lenguaje. Tenías que crear una función llamada la función constructora. Esta función hará cosas con this, no devolverá nada. Y luego, la función en sí tenía una propiedad de prototipo donde crearías cosas. Y luego, básicamente estamos tratando de obtener una nueva instancia de persona, llamarla con la función con el argumento. Y luego, usarías ese objeto como un objeto normal en cualquier otro lenguaje, llamarías métodos, proporcionarías argumentos, etc. Así que esto funciona, ¿verdad? Pero, ¿cómo funciona esto? Con estas líneas, estoy tratando de ver la estructura del objeto y el primer paso en la cadena de prototipos, y luego el segundo paso y el tercero. Si ejecuto esto, obtenemos el registro de la consola de la invocación aquí en la línea 10. Luego, la primera ejecución de console.dir nos muestra persona con el nombre Guillermo. El primer paso en la cadena es un objeto que tiene una propiedad constructor que es una función y una propiedad grid que es otra función. Y los últimos pasos son el final de la cadena con un objeto vacío y el valor nulo como se esperaba. Lo que cambia aquí del objeto que hemos visto hasta ahora en ejemplos anteriores es que tenemos este paso aquí que proporciona el método grid, la propiedad grid aquí, y esto se debe a que ejecutamos la función persona con P mayúscula con una nueva palabra clave al frente. Esta forma de llamar a las funciones está destinada a obtener nuevas instancias de alguna clase.

Entonces usaremos eso por ahora. Esta es una forma realmente complicada de hacer herencia. Algunos otros lenguajes tienen esta noción de clases que son más fáciles de entender probablemente, y no tienen cosas como __proto__, o cosas así que son realmente extrañas, pero sí, no sé, así es como diseñaron el lenguaje inicialmente.

Hagamos un pequeño experimento. Si intentamos imprimir en pantalla la propiedad a del objeto bar, será undefined, ¿verdad? Porque bar aquí no tiene una propiedad A. Y también sabemos que la propiedad A no es proporcionada por nadie en la cadena de prototipos de este objeto. Y luego lo que estamos haciendo aquí en la línea 17 es usar foo que declaramos aquí arriba como el prototipo o el primer paso en la cadena de prototipos del objeto bar, ¿verdad? Y luego, si hacemos lo mismo nuevamente, ya que foo ahora proporciona un valor para A, esto dejará de ser undefined. Podemos echar un vistazo ahora. Solo guardaré el archivo. Y ejecutaré el archivo. Y ahora, como puedes ver, el primer registro es undefined. El segundo registro no es undefined, es 44 porque A es proporcionado por alguien en la cadena de prototipos. Ok. Así que espero que eso te ayude a entender cómo funciona la cadena de prototipos, dónde comienza, cómo se referencian las propiedades, etc., etc.

Ahora hablemos un poco sobre las clases. ¿De acuerdo? Permíteme decirte que las clases no existen en JavaScript. Lo siento, pero esa es la verdad. Tenemos la capacidad de describir clases porque hay una sintaxis para ello, pero es solo sintaxis. Ahí lo tienes. Alguien lo mencionó en el chat. Es azúcar sintáctica para ti. Es para facilitarte la vida. También hay algunas verificaciones de seguridad en su lugar si usas clases, y por eso terminaremos usándolas, y te diré que por favor no hagas nada más que usar la sintaxis de clase para esto. Y ahora, para entender por qué tenemos clases hoy en día, primero debemos retroceder, como, un par de - bueno, no un par, tal vez más de un par de años atrás en el tiempo y hacer cosas como solíamos hacer cuando no había sintaxis de clase en el lenguaje. Así que consideremos el segundo archivo aquí, part2.js. He saltado a ese archivo. Aquí puedes ver las cosas que teníamos que hacer antes de que hubiera clases en el lenguaje, bueno, la sintaxis de clase que quería decir. Tenías que crear alguna función, y la convención aquí era usar mayúscula para la primera letra de la función, y esto se llamaría la función constructora, en realidad. Esta función hará cosas con this, no devolverá nada. Como esta es una función especial, ¿verdad? Alguna función que no devuelve nada, y hace cosas con this y nadie realmente sabía qué era this en realidad en este punto. Y luego, la función en sí tenía alguna propiedad de prototipo donde crearías cosas, como aquí hay una función que recibe un argumento y hace cosas con él. Y luego, básicamente estamos tratando de obtener una nueva instancia de persona, llamarla con la función con el argumento. Y luego, usarías ese objeto como un objeto normal en cualquier otro lenguaje, llamarías métodos, proporcionarías argumentos, etc. Y apuesto a que esto es casi normal, pero esto es como qué significa esto, ¿verdad? Así es como tenemos que hacer las cosas. Y ejecutemos esto rápidamente para demostrarte que esto realmente funciona. Bueno, no importa este código de consola aquí que solo está aquí para mostrar, para mostrarte qué se recibe como this. Esto es lo que dice la consola. Pero luego, sí, en la línea 12, llamamos a read. Y luego tenemos el registro de la consola justo ahí. Así que esto funciona, ¿verdad? Ahí lo tienes. Entonces, con estas líneas, lo que estoy tratando de hacer es ver la estructura del objeto y el primer paso en la cadena de prototipos, y luego el segundo paso y el tercero. Si ejecuto esto, obtenemos el registro de la consola de la invocación aquí en la línea 10. Luego, la primera ejecución de console.dir nos muestra persona con el nombre Guillermo. Básicamente, esto es lo que el lenguaje te está diciendo acerca del objeto que es una persona con una propiedad de nombre, con valor Guillermo. Ok. Luego, el primer paso en la cadena es un objeto que tiene una propiedad constructor que es una función y una propiedad grid que es otra función. Y los últimos pasos son el final de la cadena con un objeto vacío y el valor nulo como se esperaba. Lo que cambia aquí del objeto que hemos visto hasta ahora en ejemplos anteriores es que tenemos este paso aquí que proporciona el método grid, la propiedad grid aquí, y esto se debe a que ejecutamos la función persona con P mayúscula con una nueva palabra clave al frente. Esta forma de llamar a las funciones está destinada a obtener nuevas instancias de alguna clase.

8. Comprendiendo la Palabra Clave new y las Cadenas de Prototipos

Short description:

Y esta nueva palabra clave aquí cambiará, cambiará por completo la forma en que esta función se comporta. Estamos viendo aquí que es alguna persona, alguna persona vacía, realmente algún objeto vacío. Entonces, new debe estar creando ese objeto para nosotros y pasándolo a la función. Y esto se debe a que JavaScript sabe que obtuvimos este objeto de la función constructora de persona. Básicamente, lo que esto está haciendo es... Entonces, ¿por qué está aquí y qué es esto? Esta es la propiedad prototype de la función constructora. Esto se convertirá en el primer paso en la cadena de prototipos de este nuevo objeto. La propiedad __proto__ es como el inicio de la cadena de prototipos en el nuevo objeto, es lo mismo que la propiedad prototype de la función constructora. Así es como funciona. Debes crear alguna función. Luego, la función se usaría para establecer el estado del nuevo objeto, como establecer el nombre aquí en este caso, luego crearías cosas en la propiedad prototype de las funciones, y luego obtendrías nuevas instancias usando la palabra new. Y es por eso que básicamente puedes llamar a Guille.grid, Javier, aunque Guille no tenga la propiedad grid. La propiedad llamada grid es proporcionada por el prototipo de la función constructora.

Y esta nueva palabra clave aquí cambiará, cambiará por completo la forma en que esta función se comporta. Como puedes ver aquí, esto no es algún objeto global o algún objeto que conozcamos. Estamos viendo aquí que es alguna persona, alguna persona vacía, realmente algún objeto vacío. Entonces, new debe estar creando ese objeto para nosotros y pasándolo a la función. Y luego, cuando imprimimos el objeto en la consola, obtenemos esta cosa de persona delante del objeto que muestra sus propiedades. Y esto se debe a que JavaScript sabe que obtuvimos este objeto de la función constructora de persona. Básicamente, lo que esto está haciendo es... Sí, continuemos. Entonces, ¿por qué está aquí y qué es esto? El nuevo paso aquí en la cadena de prototipos. Básicamente, esta es la propiedad prototype de la función constructora. Esto se convertirá en el primer paso en la cadena de prototipos de este nuevo objeto. Espero que puedas ver que esto es realmente complicado, así que es completamente normal estar perdido en este punto, pero espero que puedas ver ahora que esto será verdadero, como lo escribí aquí, la propiedad __proto__, como el inicio de la cadena de prototipos en el nuevo objeto, es lo mismo que la propiedad prototype de la función constructora. Y si ejecuto esto con un console.log, espero obtener un true aquí. Veamos. Ahí lo tienes. True. Así es como funciona. Debes crear alguna función. Luego, la función se usaría para establecer el estado del nuevo objeto, como establecer el nombre aquí en este caso, luego crearías cosas en la propiedad prototype de las funciones, y luego obtendrías nuevas instancias usando la palabra new. Y la idea es que obtendrás un nuevo objeto y ese objeto tendrá la propiedad prototype de la función constructora como el primer paso en la cadena de prototipos de ese objeto. Y es por eso que básicamente puedes llamar a Guille.grid, Javier, aunque Guille no tenga la propiedad grid. La propiedad llamada grid es proporcionada por el prototipo de la función constructora.

9. Comprendiendo la Sintaxis y Uso de Clases

Short description:

La sintaxis de clase fue introducida en el lenguaje para facilitar las cosas y prevenir prácticas peligrosas. Llamar al constructor mismo o sin la palabra clave 'new' puede llevar a un comportamiento inesperado. Puede cambiar el objeto mismo o contaminar el contexto global. La directiva 'use strict' puede ayudar a prevenir este tipo de problemas. La sintaxis de clase es similar a otros lenguajes, con la palabra clave 'class' y un método 'constructor'. Crear nuevos métodos es sencillo y el uso es el mismo que antes. En general, la sintaxis de clase simplifica la creación y uso de objetos.

OK. Esto es muy confuso. No te preocupes demasiado si estás un poco perdido en este punto, es perfectamente normal. La idea principal es mostrarte esto para justificar por qué tenemos la clase en el texto y, con suerte, entenderlo un poco más fácilmente. La razón por la que ya no usamos esto o la razón por la que probablemente introdujeron la sintaxis de clase en el lenguaje es porque podrías hacer todo tipo de cosas que serían peligrosas para ti. Por ejemplo, podrías llamar al constructor mismo, haciendo referencia a él desde el objeto. Y esto cambiaría el objeto mismo, lo cual es realmente confuso. Ahora el objeto tiene una propiedad de nombre bar, lo cual es muy inesperado, porque estás llamando a algún constructor. Luego, tal vez esperarías obtener algún objeto o algo así. Esto no tiene sentido en absoluto. Es peligroso hacer cosas así. Otra cosa que podrías hacer es tomar el constructor y llamarlo con algo extraño como este, como en este caso, y luego esperar que este objeto sea algo. Esto no funciona, por supuesto. Javier será indefinido porque la función constructora no devuelve nada. No utiliza la palabra clave 'return'. Entonces, cualquier cosa que intentes asignar... esto no funcionará como esperas. Y esto es realmente lo más peligroso que podrías hacer con una función constructora, llamarla sin usar la palabra clave 'new' aquí. Como no estoy usando 'new'. Esto es realmente peligroso y esto fue uno de los principales problemas que esto crearía. Y esto es peligroso porque si no usas 'new', entonces el lenguaje asignará esto como el objeto global. Como puedes ver aquí, esto es el objeto global, como puedes ver aquí. Y lo que esto significa es que esto se ejecutará y básicamente estamos agregando alguna propiedad de nombre en el objeto global, lo cual, ya sabes... Es contaminar el contexto global y esto es algo en lo que todos están de acuerdo que no es bueno hacer. Y luego no obtendrás nada de nuevo porque la función persona no devuelve nada y luego Javier será indefinido, como puedes ver aquí. Y luego la propiedad de nombre en el contexto global se establecerá en algo. Así que imagina que estás haciendo esto mucho y luego un par de constructores usan la misma propiedad de nombre. Entonces, el último que ejecutes sobrescribirá el valor y puedes esperar todo tipo de comportamientos incorrectos y esto es realmente difícil de depurar también. Sí. Todos estuvieron de acuerdo en que tener que pasar por todos estos obstáculos solo para obtener un objeto era una mala idea, pero diseñaron el lenguaje, por lo que introdujeron la sintaxis de clase. Exactamente, sí. Alguien también menciona la directiva 'use strict' o palabra clave, no sé cómo llamarlo realmente, pero apuesto a que ya lo has visto en algún lugar. Esto es algo que colocas al comienzo del script y luego el lenguaje te impedirá hacer cosas locas como esta, realmente se quejará, pero necesitas hacerlo para no olvidarte de hacer esto. Entonces, para hacer las cosas mucho, mucho más fáciles para todos, el lenguaje introdujo la sintaxis de clase y espero que todos estemos de acuerdo en eso. Es mucho más fácil y mucho más agradable obtener el mismo resultado, ¿verdad? En primer lugar, estamos usando una sintaxis que es muy similar a otros lenguajes. Aquí tienes la palabra clave 'class'. Hay un método especial. En este caso, se llama 'constructor'. En Ruby se llama 'initialize'. En Java tiene el mismo nombre que la clase. Diferentes lenguajes tienen diferentes convenciones, pero todos podemos estar de acuerdo en que es fácil de identificar. Este es el constructor que vamos a usar. Y luego la sintaxis para crear nuevos métodos también es agradable. No hay propiedades de prototipo extrañas. Sí. Nada realmente. Todo parece estar bien hasta ahora, o eso espero. Y luego la parte de uso es exactamente la misma. Usas 'Neo' en el nombre de la clase y simplemente usas los métodos aquí. Y el resultado también es el mismo. Si ejecuto este archivo ahora, es la parte tres.

10. Azúcar Sintáctico e Invocación del Constructor

Short description:

Si ejecuto esto, obtengo una persona con una propiedad de nombre Guillermo. Las clases son azúcar sintáctico que proporciona seguridad al obligar el uso de 'new' al invocar constructores. Es importante usar esta sintaxis correctamente para evitar problemas a largo plazo.

Si ejecuto esto, obtengo lo mismo. Obtengo una persona con una propiedad de nombre Guillermo. Obtengo un primer paso de la cadena de prototipos que se ve muy similar al que obtuve con la cadena de prototipos. Y luego los dos últimos pasos son el valor nulo y el objeto vacío. Todo se ve bien. No es exactamente lo mismo. Si analizamos esto con la sesión de depuración, etc., veremos que son cosas diferentes, pero en general se aplican los mismos conceptos. Y aquí también puedes ver que las clases son realmente azúcar sintáctico porque en el fondo lo que tienes es una cadena de prototipos igual que la que tenías antes. Y aquí está la mejor parte de esto es que obtienes mucha seguridad de ello. Si intentas usar el constructor de forma aislada, bueno, no de forma aislada, invocarlo como un método, el lenguaje se quejará. Te dirá que no se puede invocar a persona sin el new. Si intentas ejecutarlo de forma aislada sin una llamada, también se quejará. Lo mismo, necesitas invocarlo con new. Y si intentas llamar a la función constructora sin new, también se quejará. Mucho más seguro usar esta sintaxis. Así que en general, te diría, por favor, nunca intentes hacer algo como esto a menos que seas súper, sepas lo que estás haciendo básicamente porque será malo para ti a largo plazo. Genial, ahí lo tienes, genial.

11. Diferencia entre Invocación y Código en JS

Short description:

En JavaScript, los términos invocado, ejecutado y llamado son sinónimos cuando se refieren a código. El método 'call' en las funciones te permite pasar un contexto y argumentos como valores separados por comas. Por otro lado, el método 'apply' requiere que los argumentos estén en forma de array. Ambos métodos tienen sus usos, dependiendo de la situación. En general, todos se refieren a la misma acción de ejecutar código.

Entonces alguien está preguntando, ¿cuál es la diferencia entre invocación y código en JS? Creo que es un sinónimo. Puedes usarlo así, cuando hablas de código, invocar una función, llamar una función, ejecutar una función, todo es lo mismo. Tal vez el verbo 'call' tenga un significado especial porque hay un método 'call' en las funciones. Permíteme mostrarte eso. Así que la función completa.call, ya lo hemos visto, ¿verdad? Puedes pasarle un contexto. Y esto tiene un significado especial porque si la función completa tuviera algunos, voy a eliminar todo esto solo para hacer espacio y ser muy específico al respecto. Si la función completa tiene argumentos, A, B, C, y estás tratando de invocarla con call, entonces necesitas proporcionar los argumentos como valores separados por comas. Mientras que, por ejemplo, si usaras apply, el primer argumento es el mismo, pero luego los argumentos de la función en sí deben estar en forma de array. A veces es más fácil usar apply porque tal vez estés obteniendo los argumentos de alguna otra llamada de función y ya están en forma de array. Entonces hacerlo así es más apropiado o más, ya sabes. Solo opciones que tienes, call y apply. Pero sí, invocar, ejecutar, llamar, lo que quieras. Creo que es lo mismo. Espero que eso responda tu pregunta.

12. Objetos Literales, Clases y el Patrón de Módulo

Short description:

Los objetos literales y las clases en JavaScript no tenían la capacidad de ocultar información hasta Node.js 12. Con Node.js 12, puedes declarar propiedades privadas en clases usando el prefijo de almohadilla (#). Estas propiedades privadas solo pueden ser accedidas dentro de la clase. El lenguaje impide el acceso a las propiedades privadas desde fuera de la clase, brindando un mayor nivel de seguridad. Antes de Node.js 12, se utilizaba el patrón de módulo para ocultar información. El patrón de módulo involucra el uso de funciones que retornan algo, creando un ámbito local donde se declaran funciones y variables, asegurando que permanezcan ocultas fuera de la función.

De acuerdo, una vez más, vamos a la parte tres, parte cuatro. Nuevamente, cómo obtener un objeto. Ya hemos usado esta notación aquí. Correcto, esto se llama objeto literal. Y probablemente esta sea una de las formas más fáciles de obtener un objeto, simplemente abres una llave, luego colocas las propiedades, dos puntos y luego el valor y puedes tener más de ellos. Y sí, eso funciona e incluso, ups, eso no es lo que quería hacer. Incluso puedes tener métodos y ahora es probablemente mejor si lo formateo de una manera que sea fácil de leer.

Muy bien, esta es la notación de objeto literal, una de las formas más fáciles de obtener un objeto. Otra forma es usando clases, por supuesto. Bueno, alguien en el chat menciona object.create así que llegaremos a eso al final. Y podemos hablar de eso más tarde. Sí, objeto literal, usando clases para obtener nuevos objetos a partir de él. Pero luego, ¿qué sucede aquí es que tanto los objetos literales como las clases hasta Node.js 12, versión 12, no tenían la capacidad de ocultar cosas. Todo era público. Cada objeto, tú como usuario de ese objeto tendrías acceso a todo lo que está declarado en ese objeto. Y no sé si sabes eso, pero en la programación orientada a objetos, la encapsulación es algo importante. Deberías tener o deberías diseñar tus clases y objetos de manera que encapsulen los detalles de implementación internos de ese objeto y solo expongan una API pública o un conjunto público de datos que los usuarios deben usar y no las partes internas. Eso es básicamente encapsulación. Y en JavaScript, antes de Node.js 12, si estabas usando clases o estabas usando objetos literales, no podrías hacer eso. Te verías obligado a diseñar tus activos, haciendo todo público y tal vez probablemente teniendo algunas convenciones sobre poner un guión bajo al inicio de un nombre de propiedad, tal vez para indicar que no debes usar eso o lo que sea pero no había reglas estrictas al respecto. Esto era especialmente problemático al tratar con objetos provenientes de frameworks y bibliotecas. Pero después de Node.js 12 resulta que realmente puedes tener cosas privadas en clases. Y la forma en que esto funciona es usando, bueno, esto se llama almohadilla. Por alguna razón, le llaman almohadilla. Así que sigamos con eso. Entonces declaras la propiedad name como privada agregando el prefijo de almohadilla. Y luego lo que obtienes es que podrás hacer referencia a esa propiedad con la almohadilla, lo que sea dentro de la clase, pero no fuera de la clase. El lenguaje te impedirá acceder a eso. Así que ejecutemos esto primero para ver que funciona. Ahí lo tienes. Y de inmediato puedes ver que cuando hago console.log del objeto, no veo nada sobre la propiedad name. Y siendo JavaScript, el lenguaje que es, donde básicamente puedes hacer lo que quieras en memoria, como en runtime, podrías pensar, okay, sé que name existe. Solo voy a agregar un método al objeto dinámicamente que lo devuelva y listo. Y esto debería funcionar, ¿verdad? Bueno, tengo malas noticias para ti. Esto no va a suceder. Y en realidad, esto es una buena medida de seguridad, creo porque te dirá que name es privado y necesitas declarar este método en el objeto. Lo siento, en la clase. Básicamente, esto te está diciendo que necesitas tener acceso al código fuente y debes poder implementar el código fuente en donde sea que se esté ejecutando esto. Así que estas son, esto es un alto estándar de seguridad en mi opinión. No es como, esto es un signo de madurez para mí. El lenguaje se está volviendo realmente maduro de alguna manera. Así que sí, a partir de Node.js 12, puedes hacer esto. Así que yay, estas son buenas noticias. Antes de Node.js 12, sin embargo, ¿cómo lidiarías con esto? A veces no podías lidiar con esto porque realmente necesitabas una clase. Tal vez esto era un modelo que se iba a instanciar muchas veces, así que realmente necesitabas una clase para hacer que todo el proceso sea liviano. Pero a veces, estabas diseñando algún servicio que solo ibas a instanciar una vez, ¿verdad? Entonces, cuando ese era el caso, y nos estamos moviendo al archivo de la parte cinco, usarías el patrón de módulo. Y el patrón de módulo en Node, en JavaScript, se trata simplemente de usar funciones que retornan algo. Y lo que obtienes al hacer esto es que cada vez que abres la llave aquí para comenzar a implementar esta función, obtienes un ámbito local donde puedes declarar funciones y variables, y nada de eso escapará de ese ámbito local, lo que significa que fuera de la función, cualquier cosa que crees dentro de esa función se mantendrá oculta. Como si nadie pudiera acceder, ¿verdad? Lo siento. Siguiendo esta estructura aquí, lo que estoy haciendo aquí es crear una función que se llama gritter con G mayúscula que retorna otra función, es anónima, no tiene nombre.

13. Encapsulación y el Patrón de Módulo

Short description:

La función gritter recibe un nombre y devuelve una función que toma otro nombre e imprime algo en la consola. El valor del argumento nombre está encapsulado y se vuelve privado. La instancia de la función se identifica por el lenguaje y se incluye en la cadena de prototipos. Esta construcción se utiliza comúnmente al diseñar servicios. El patrón de módulo permite la creación de elementos privados y públicos. El objeto devuelto incluye el cierre que extrae todos los valores necesarios. El patrón de módulo es una forma de implementar objetos donde todo es privado por defecto. La cadena de prototipos se actualiza en consecuencia y el patrón de módulo se puede ejecutar sin contaminar el contexto global.

Y la función gritter recibe un nombre. Y la función que devuelvo toma otro nombre e imprime algo en la consola. Así que el trato es que una vez que llamo a la función con G mayúscula, obtengo la función y en este punto, el argumento nombre como Guillermo, este valor aquí está fuera de alcance. Nadie puede acceder a través de la manipulación del objeto Gritters Guilli, nadie puede acceder a ese valor. Lo estoy ocultando, lo estoy encapsulando, lo estoy haciendo privado y lo estoy entrecomillando aquí. Y básicamente esa es la forma de lidiar con eso. Estoy usando funciones y las variables locales, el ámbito de variables de las funciones para ocultar cosas y solo devolver, publicar o hacer público o lo que sea que esté devolviendo. Y si ejecuto esto y echo un vistazo a los prototipos, etc., lo que veré es, bueno, esta es la línea que obtengo al llamar a la función en sí. Pero luego, sí, los dos últimos pasos son los que esperamos, el valor nulo y el objeto vacío. Y luego hay un tercer paso, un paso especial aquí. Entonces, y esto es, esta es la instancia de la función. Lo siento. Básicamente, el lenguaje identificará esta variable gritter sguille como una función al ponerla en la cadena de prototipos. Y por cierto, esto también es lo que me proporciona los métodos bind y call que ya hemos mencionado. Genial, tal vez sea difícil ver el valor de esta construcción con un módulo tan simple aquí. Pero si pasamos al siguiente archivo, part6.js, verás que esto es en realidad algo que hice todo el tiempo. Cada vez que tenía que design un servicio, lo hacía de esta manera. Creaba un módulo para el servicio, creaba cosas aquí, y luego al final del módulo, devolvía un objeto. Y ese objeto es la API del servicio. Y aquí, lo que estoy haciendo es crear tres funciones. Y solo estoy devolviendo dos de ellas, crear y guardar archivo. Bueno, estoy devolviendo un objeto que tiene una propiedad que tiene un valor de una función que se declara en el ámbito local del módulo reader two. ¿Verdad? Mm-hmm. Sí, y el objeto que estoy devolviendo aquí incluye la definición de la función log. Porque, ya sabes, el objeto depende de grit y grit depende de log. Y log no depende de nada. Entonces esto funciona porque el objeto que devuelves incluye el cierre que extrae todos los valores que necesita para funcionar. Y aquí podrías hacer cualquier cosa que quieras, como crear const A 42. Y luego usarlo aquí. Y nadie va a tener acceso a A a menos que lo publiques explícitamente a través del objeto que estás devolviendo. Espero que esto tenga sentido. Como, la forma de hacerlo público es incluirlo como valor de retorno. Entonces, básicamente, en cierto sentido, esta es una forma de implementar objetos o describir objetos de manera que todo sea privado por defecto y luego elijas específicamente qué quieres hacer público. Sí. Genial. Así que si ejecuto esto ahora. Permíteme limpiar la pantalla. Lo que vemos es que ahora la cadena de prototipos tiene, bueno, como siempre, el valor nulo fue el último. Antes de eso, está el objeto vacío y ahora tenemos el, el objeto gritter tiene una propiedad saludar y una propiedad despedirse, como esperamos. Y sí. Solo un par de notas sobre el patrón de módulo aquí. Tienes un par de ejemplos en la parte siete, eso es JS. El primero aquí se llama la función de autoejecución. Apuesto a que la mayoría de ustedes han visto alguna forma de esto en algún lugar. Esta es... una forma de declarar un módulo y ejecutarlo sin contaminar el contexto global. Porque esta función no tiene un nombre. No necesita un nombre. Porque la ejecutamos con estos paréntesis justo después de declararla. Así que no necesita un nombre.

14. Objetos y Módulos en JavaScript

Short description:

Por lo tanto, los objetos en la transpilación de código y el empaquetado de software se envuelven con funciones autoejecutables para evitar la contaminación del contexto global. Node.js utiliza un envoltorio de módulo para proporcionar argumentos y envolver archivos. Comprender las cadenas de prototipos es útil para solucionar problemas en sistemas y trabajar con objetos de bibliotecas y frameworks. Dependiendo de la necesidad de múltiples instancias, se pueden utilizar clases o módulos. Los módulos, que involucran funciones y ámbitos de variables, pueden ser una solución más simple en algunos casos.

Por lo tanto, no es necesario almacenarlo en el contexto global de ninguna manera. Simplemente se declarará y se ejecutará. Ambas cosas en secuencia. Y no hay contaminación del contexto global. Esta también es la forma en que la mayoría de la transpilación de código y el software de empaquetado funcionan, como Webpack y otros, tomarán tus fuentes de TypeScript. O cualquier otro lenguaje que estés utilizando en estos días. Tomarán eso, lo transpilarán, y lo envolverán con funciones autoejecutables para que cuando se entregue en un navegador se ejecute y no haya efectos secundarios en el contexto global tampoco.

Y el segundo ejemplo aquí es lo que Node.js realmente utiliza para envolver tus archivos de Node.js. Este es el envoltorio de módulo. Y puedes ver aquí que recibirá los exports, require module y otros argumentos que están disponibles en tus archivos. Como se proporcionan por Node.js cuando envuelve tu archivo con esta función autoejecutable.

Y sí, con eso, hemos cubierto todo el contenido que quería revisar sobre los objetos. Todavía tenemos una pregunta por abordar. Y antes de hacerlo, por qué creo que esto es útil para mí, esto es útil, especialmente para solucionar problemas en sistemas. Y especialmente cuando los objetos provienen de bibliotecas y frameworks porque cuando estás con el sistema final para el usuario final, tu diseño tiende a ser más plano, probablemente, y las jerarquías de tipos son planas allí. Entonces no hay mucho en la cadena de prototipos. Pero cuando estás tratando con objetos que provienen de frameworks y bibliotecas, frameworks y bibliotecas están diseñados para ser reutilizables y abstractos, y eso se logra de muchas maneras y algunas de ellas tienen que ver con jerarquías de tipos complejas que requieren cadenas de prototipos complejas. Entonces, cuando obtienes uno de esos objetos, es realmente útil conocer cómo funcionan las cadenas de prototipos y cosas así y saber cómo funciona la instanciación porque cuando hay un problema con esos objetos, puedes investigar y obtener la respuesta más rápido si no lo supieras, por supuesto. Y luego, una segunda forma en la que creo que esto es útil es porque ahora puedo preguntarme a mí mismo al diseñar un nuevo sistema, puedo preguntarme, ¿necesitaré muchas instancias de lo mismo? Entonces, probablemente tendría que diseñar una clase porque tener una cadena de prototipos es una forma más rápida de asegurarse de que todos los objetos tengan los mismos métodos y propiedades. Tal vez solo vaya a tener una instancia de ello, es un Singleton o un servicio o algo así. Entonces, probablemente pueda arreglármelas con solo un módulo. Y, esto también, todos pueden pensar de manera diferente aquí, pero creo que estos módulos aquí, ya que no tienen que ver con prototipos o clases o herencia, no necesitas usar new en absoluto. Son solo funciones y ámbitos de variables. Para mí, eso aporta menos complejidad a la solución. Entonces, va más en el estilo que me gusta, entonces tal vez use esto en lugar de usar una clase de la cual solo instancio un objeto. Pero ahora tengo opciones y eso es lo que realmente valoro. Y ahora sería un buen momento si tienen alguna pregunta, pueden hacerla en el chat de Zoom.

15. Usando Object.create en JavaScript

Short description:

Algunas personas piensan que usar object.create con null es más rápido y tiene un menor consumo de memoria. Sin embargo, en la mayoría de los escenarios, se considera una sobreingeniería. Object.create con null crea un objeto sin una cadena de prototipos, lo cual puede causar problemas con ciertos métodos. Object.create y Object.assign son útiles en escenarios específicos, pero comprender el ObjectLiteral, la instanciación de clases y los módulos son las principales formas de crear objetos en JavaScript. Object.create es más adecuado para casos de uso avanzados, como el diseño de videojuegos o trabajar con objetos livianos.

Y tengo una pregunta de alguien que está preguntando, ¿has usado seriamente object.create con un no prototipo en producción? Esa es una muy buena pregunta. Es, en mi opinión, es un tema muy avanzado para hablar probablemente. Pero sí, vamos a intentarlo, ¿de acuerdo? Entonces, esta persona se refiere a esta cosa que puedes hacer, object.create, ups, create. No, eso no es lo que quería decir. Y aquí, si no me equivoco, puedes pasar el prototipo aquí, ¿verdad? Si paso null aquí, y lo asigno a una variable así, y luego hago console.dir a, y luego intento hacer eso, y lo ejecuto, ahí lo tienes. Entonces, a es un objeto con un prototipo nulo, y la propiedad del prototipo de ese objeto es undefined. Entonces, básicamente, lo que obtenemos al hacer object.create con null es un objeto que no tiene una cadena de prototipos. Algunas personas piensan que esta forma de crear objetos es más rápida, tiene un menor consumo de memoria. Esto puede ser relevante cuando estás lidiando con un código altamente eficiente que necesita ser muy rápido. Diría que en el 99.9999% de los escenarios, de los escenarios, esto es como una sobreingeniería. Como, ¿por qué no simplemente, ya sabes, cuál es el problema de hacer eso, ¿verdad? Pero otro efecto secundario de seguir este camino es que ahora A to string no existe, y esto fallará. Ahí lo tienes, A to string no es una función, ¿verdad? uh. Sí, algunas personas están respondiendo porque no estás arrastrando las propiedades predeterminadas o lo usaría para proteger contra una cadena de prototipo de entrada insegura. Oh, ese es un buen punto, sí. Bueno, esos son puntos válidos, si ese es tu escenario, adelante y úsalo. Estos dos tienden a ir juntos, como object create y object assign. Te animo a investigar la investigación, aprender sobre ellos. Están ahí porque son útiles en algunos escenarios. Normalmente, lo que argumentaría es que el ObjectLiteral, la clase, ups, la instanciación o simplemente, ya sabes, llamar a un módulo que te da un ObjectLiteral son las tres formas principales de crear objetos que todos deberían entender y dominar. Y luego, si tu escenario requiere más, sí, ¿por qué no? ObjectCreate está ahí para ti. Y ObjectAsign, si es necesario. Hay herramientas que puedes usar. Pero sí, esto es honestamente, esto es avanzado. Tal vez estés diseñando video juegos en JavaScript o tal vez estés haciendo cosas de machine learning o, no sé, tal vez tu caso de uso crea, requiere objetos realmente livianos y eso es útil o tal vez para validación o alguien... y seguridad como alguien sugirió.

16. Introducción a la Programación Asincrónica

Short description:

JavaScript proporciona un único hilo para los programas, que encola y ejecuta instrucciones. Otros lenguajes tienen un enfoque multihilo, lo que permite un mayor control y uso de recursos. Sin embargo, esto conlleva una mayor complejidad y desafíos de depuración. JavaScript simplifica el proceso de trabajar con programas asincrónicos sin bloqueo. Alegrémonos por ello y sigamos adelante.

Vale, primero que nada, mi objetivo en esta sección es convencerte. Si aún no estás convencido, por supuesto, de que en realidad JavaScript es un lenguaje realmente bueno para trabajar con programas asincrónicos sin bloqueo. Y primero, necesitamos establecer que esto es algo que realmente necesitamos. Como, ¿por qué alguien haría eso consigo mismo? ¿Verdad? Y es, como si esto fuera necesario, como si no pudiéramos evitarlo. Las operaciones de entrada/salida son lentas y no podemos tener el hilo bloqueado mientras obtienes algunos datos de un servidor de terceros o escribes archivos en el sistema de archivos. No puedes tener la CPU detenida esperando que eso termine. Y esto es especialmente importante al tratar con interfaces de usuario, ¿verdad? Sería una muy mala experiencia de usuario si la pantalla se congela cuando se cargan los elementos de un desplegable para elegir. Nadie hace eso en estos días, las aplicaciones tienden a ser asíncronas porque es simplemente mejor. Entonces, JavaScript resuelve esto hay varias formas de resolver este problema, ¿verdad? En JavaScript, lo que hace JavaScript, es proporcionarte un hilo, un único hilo para tu programa, y luego cada instrucción que debe ejecutarse se coloca en esa cola, y lo que el motor hace es recorrer esa cola hasta que no haya nada más que ejecutar, y luego deja de funcionar. Entonces, cuando estás escribiendo un programa JavaScript, básicamente le estás diciendo a JavaScript qué instrucciones deben encolarse y en qué orden debe ocurrir eso. Otros lenguajes, como Java, por ejemplo, tienen un enfoque multihilo, y ese enfoque probablemente sea mucho más potente, te permite tener más control, y lo que es más importante, te permite utilizar todos los recursos que tienes en el servidor o la computadora en la que se ejecuta tu programa. Si tienes ocho núcleos, realmente puedes aprovechar todo de ellos, hacer que funcionen al 100% de ocupación de tiempo, y realmente, ya sabes, extraer todo el poder de la plataforma en la que se ejecuta tu programa. En Node.js y en general en JavaScript, no tienes esa opción. Solo tienes un hilo. Si tienes 10 núcleos, tendrás que usar algo encima de tu programa Node.js para aprovechar todo ese poder de la plataforma. Así que solo tienes un hilo, y otros lenguajes te permiten acceder a todos los hilos que puedas obtener de la plataforma. Pero el inconveniente es que traen mucha complejidad. Necesitas ser un programador realmente experto para diseñar programas de manera que sean fáciles de entender y fáciles de mantener. Y también otro inconveniente es que cuando las cosas fallan, un programa multihilo es mucho más difícil de depurar que, ya sabes, te metes en problemas más grandes probablemente. Entonces, primero, justo en la introducción, te digo que en resumen, probablemente deberíamos estar contentos. JavaScript resuelve este problema difícil de resolver de una manera sencilla. Sé que al principio puede ser abrumador, pero espero que con las cosas que vamos a ver ahora tengas las herramientas para pensar en ello de una manera más eficiente y más sencilla. Pero sí, en resumen, podría ser peor. Alegrémonos por ello. JavaScript es increíble. Sigamos adelante.

17. Entendiendo el Comportamiento Asincrónico en JavaScript

Short description:

En JavaScript, el comportamiento no bloqueante se describe a través de funciones de devolución de llamada. Jugaremos con la función setTimeOut para entenderlo. El orden de ejecución es A, C, D con un retraso de un segundo entre C y B. En el segundo archivo, el hilo se detiene durante dos segundos y la secuencia es A, setTimeOut de B con un retraso de un segundo, y C. ¿Puedes adivinar la secuencia y cómo se desarrollarán los retrasos?

Muy bien, entonces en JavaScript, el comportamiento no bloqueante o comportamiento asíncrono se describe a través de funciones de devolución de llamada. Y estas son funciones que se van a llamar en algún momento en el futuro. Como, eso es literalmente lo que significa, ¿verdad? Y para entenderlo, primero juguemos con un fragmento de código que tengo aquí. Vamos al directorio async en el archivo part1.js. Veamos. Sí, vamos a jugar con la función setTimeOut. Y la función setTimeOut te permite... te permite poner aquí una función y un retraso. Y la promesa es que esta función se llamará en no menos de 1,000 milisegundos, un segundo aquí. Ups, alguien está cambiando ese directorio. Oh. De acuerdo, genial. Entonces, este código aquí va a imprimir A. Luego llama a setTimeOut en una función que imprimirá B. Y luego imprimirá C. Y aquí están los desafíos. ¿Puedes adivinar el orden real de estos fragmentos? Te dejaré pensar en esto por un minuto. También puedes ejecutarlo en la terminal si quieres ver qué sucede en realidad. Pero me gustaría, intentemos... Antes de ejecutarlo, intentemos hacer una suposición. De acuerdo, alguien ya está haciendo apuestas en el chat. A, C, D, por ahora, B, A, de acuerdo. No sé qué fue eso. A, C, D, genial. Genial, vamos a ejecutarlo. Supongo que podemos verlo, ¿verdad? A, C, parte uno. Genial, el orden es A, C, D. Ahí lo tienes. A, C, D, todos tenían razón, supongo. La parte interesante aquí es que hay un pequeño retraso entre C y B porque podemos verlo, ¿verdad? La función setTimeout establece un retraso de un segundo. Así que esto es esperado. A, C, un segundo, luego B. De acuerdo, todo está bien. Nadie hizo una suposición diferente, así que creo que podemos pasar al segundo archivo. Y aquí en este archivo, lo que estoy haciendo es, estoy usando este módulo aquí llamado sleep que va a detener el hilo y evitar que se ejecute cualquier cosa durante dos segundos. Y aquí, nota que dos segundos es más que un segundo, ¿verdad? Entonces, y es la misma secuencia. Console log A, setTimeout de console log B. Un segundo de retraso. Detener el hilo durante dos segundos y console log C. Nuevamente, voy a reiniciar aquí. Haz una apuesta, como cuál será la secuencia. Tal vez también puedas describir cómo se desarrollarán los retrasos en el resultado final. ¿Puedes adivinar eso? De acuerdo. De acuerdo. Tenemos la primera suposición de ACB. Tal vez puedas explicar. Oh, tenemos un ABC. Esto se está poniendo interesante. Si también puedes razonar cómo se desarrollarán los retrasos, eso sería genial. ABC, ABC.

18. Cola de Eventos de JavaScript y setTimeout

Short description:

Entonces, ABC está ganando en este momento. El orden de los bloqueos debe ser el mismo. El hecho de que no estemos esperando ningún milisegundo en absoluto no cambia el hecho de que esto está encolando el registro primero, esto está encolando la llamada de setTimeOut, y esto está encolando el registro C. La ejecución de setTimeOut encola esta llamada aquí. El modelo mental que sigo, la forma en que pienso sobre el comportamiento asíncrono en JavaScript, tiene más que ver con encolar cosas como hicimos aquí y entender cuál será el desencadenante. Esos son diferentes desencadenantes que se tendrán en cuenta cuando esa devolución de llamada sea lo próximo en ejecutarse, ¿verdad?

Entonces, ABC está ganando en este momento. De acuerdo, entonces... Costo del ciclo de vida de node.js. De acuerdo. Eso es cierto. Creo que sí, la persona que adivinó ACB tiene razón. Echemos un vistazo. ACB. Entonces, en primer lugar, el orden es el mismo. Nuevamente, debes pensar en esto como, hay un solo hilo y hay una cola de instrucciones. Y la cola de instrucciones es la misma con la única diferencia de que antes de imprimir C hemos esperado dos segundos. Pero todo lo demás es igual, ¿verdad? Entonces, el orden de los bloqueos también debe ser el mismo.

Lo interesante aquí es que estamos esperando dos segundos entre A y C y luego B se imprime justo después, casi instantáneamente. Entonces, lo que vemos aquí es que no hay un segundo adicional de retraso después de esperar dos segundos. Esto es lo que hace setTimeOut, me permite describir un retraso que comienza desde la última instrucción ejecutada, bueno, la última instrucción encolada. Entonces, dado que esperamos dos segundos, dos segundos son más que uno. Imprime b instantáneamente, no necesita esperar más. De acuerdo. Genial, ahora pasemos al tercer ejemplo. Y aquí no vamos a bloquear el hilo ni nada por el estilo, pero estableceremos el tiempo de espera en cero milisegundos. Entonces, en tu opinión, ¿esto cambiará algo? ¿Se verá afectado el orden? O sí, haz tus apuestas, supongo.

De acuerdo, ACB no cambiará, sigue siendo el mismo. ACB también. Sí, tienes razón, básicamente no cambiará. ACB de nuevo, sí. Así que ya entiendes cómo funciona esta cola. Estoy contento por eso. Entonces, ACB, el orden es el mismo, el hecho de que no estemos esperando ningún milisegundo en absoluto no cambia el hecho de que esto está encolando el registro primero, esto está encolando la llamada de setTimeOut, y esto está encolando el registro C. Y luego, cuando se llama a esto, se encola en la última posición, y luego, sí, entonces la pila, en este momento, tiene A, ahora la pila tiene A, y el setTimeOut, estoy improvisando aquí, y luego aquí, la pila tiene setTimeout, y luego C, y luego cuando esto se ejecuta, como, el motor comienza, en realidad, a tomar instrucciones y ejecutarlas, tomará A, y la pila tiene setTimeout, y C, luego toma el setTimeout, y lo ejecuta. Y la pila tiene C, y como resultado, la pila ahora tiene C y B, porque la ejecución de setTimeout encola esta llamada aquí. Y luego, finalmente, se toma C, B aún está pendiente de ejecución, y luego se toma B, la pila está vacía, y el programa termina. Oh, de acuerdo, espero que esto haya sido improvisado. No tenía planeado explicarlo de esta manera, pero espero que tenga sentido. De todos modos. Uh, genial. Sí, de nuevo, lo mismo, solo, ya sabes, estamos jugando con el hecho de que solo hay un hilo, y hay una cola de instrucciones que se ejecutarán, y setTimeout es realmente, ya sabes, tiene este nombre muy engañoso de tiempo de espera cuando en realidad, está encolando cosas con un desencadenante basado en el tiempo, o no sé. El modelo mental que sigo, la forma en que pienso sobre el comportamiento asíncrono en JavaScript en general, tiene más que ver con encolar cosas como hicimos aquí, y entender cuál será el desencadenante. En el caso de un setTimeout, va a encolar como sucedió aquí. Va a encolar B, pero es B con un asterisco porque no es como si el intérprete no sacara B de la pila si no ha pasado suficiente tiempo porque tal vez necesito esperar dos segundos. Si no ha pasado suficiente tiempo, B se quedará en la pila hasta que haya transcurrido ese tiempo y luego se ejecutará una vez que haya pasado ese tiempo. Y esto es exactamente lo mismo cuando hablamos de una llamada AJAX en la noche, por ejemplo, no es un desencadenante basado en el tiempo. Es un desencadenante que se basa en alguna operación de entrada y salida que ocurre en la capa de red cuando se realiza alguna solicitud a algún servidor y luego el sistema operativo recibe la respuesta y la analiza, blah, blah, blah. Y luego el desencadenante es como mi devolución de llamada para la llamada AJAX va a ser que tengo la respuesta y la respuesta debe ser analizada y luego se llama a la devolución de llamada. Y hasta que esa respuesta esté disponible, la devolución de llamada estará en la cola esperando ser ejecutada. O por ejemplo, si estoy escribiendo un archivo en el sistema de archivos, el desencadenante será que esa operación de escritura se complete. Y luego, el modelo mental, todo es lo mismo. Son solo devoluciones de llamada que están encoladas. Están en la cola esperando ser ejecutadas y se ejecutarán según algún desencadenante y dependiendo de si las encolamos con un setTimeOut o una llamada AJAX o una escritura de archivo. Sí, esos son diferentes desencadenantes que se tendrán en cuenta cuando esa devolución de llamada sea lo próximo en ejecutarse, ¿verdad? Así es como pienso en estas cosas.

19. Usando Promesas para Programación Asincrónica

Short description:

Las devoluciones de llamada pueden volverse complejas cuando se trata de múltiples operaciones y efectos secundarios. La API de promesas de JavaScript simplifica la programación asíncrona al proporcionar patrones de diseño para la coordinación. El ejemplo de función no bloqueante demuestra el uso de promesas para secuenciar devoluciones de llamada en un orden específico. Encadenar devoluciones de llamada en promesas permite crear una tubería funcional de funciones que procesan valores y los pasan a lo largo de la cadena. Las promesas permiten descomponer los efectos secundarios en fragmentos más pequeños y describir el orden de las operaciones.

Y esta cosa de las devoluciones de llamada funciona muy bien. Es lo suficientemente simple cuando estás lidiando con una sola devolución de llamada que debe ejecutarse, cuando esa devolución de llamada es lo suficientemente simple, como si fueran un par de líneas, probablemente no es demasiado compleja, pero muchas veces necesitas hacer cosas más complejas. Tal vez necesites ejecutar una devolución de llamada enorme que hace muchas cosas, o tal vez necesites coordinar una primera llamada a un servicio y luego una segunda llamada a otro servicio, y luego tal vez necesites escribir algo en un archivo versus algo en la base de datos, y blah, blah, blah. Puede volverse realmente complicado, ¿verdad?

Y cuando las operaciones están terminadas, alrededor de eso, son síncronas, se trata solo de escribir tu programa y ya está. Pero cuando todo comienza con una operación no bloqueante, como una llamada AJAX o leer un archivo del sistema de archivos, lo que sea, hacer esa coordinación y descomponer cada efecto secundario en una función pequeña y digerible que solo se ocupe de una cosa, eso es algo difícil de hacer solo con devoluciones de llamada. Si eres un desarrollador de software experto en programación funcional, tienes muchas herramientas para hacer eso, composición de funciones, puedes tener mónadas, puedes tener, tienes muchas herramientas y eso es perfecto. Perfecto. Pero si no tienes la experiencia, o tal vez estás trabajando con un equipo con diferentes niveles de conocimiento, o tal vez hay especialistas o especialistas en programación funcional, pero hay otros especialistas que no tienen eso, ese conocimiento y son más expertos, no sé, en UX o lo que sea. Y ellos saben sobre programación funcional. Y hacer esa coordinación es realmente complicado y hará que cosas como la colaboración sean más difíciles en general. Entonces, ¿qué hacer entonces, verdad?

La conclusión es que quieres usar patrones de diseño estándar que se aplican a la programación asíncrona. Y la buena noticia aquí es que JavaScript te proporciona una API de promesas que implementa un par de patrones de diseño útiles que te permiten hacer precisamente estas cosas de coordinación de una manera más fácil, de una manera más sencilla. Y tenemos un ejemplo de eso en la Parte 4. Como una introducción realmente rápida a las promesas. Y la Parte 4 probablemente tenga una de las formas más simples de introducir esto. Básicamente, lo que estoy creando aquí es una función llamada función no bloqueante. Toma un retraso y devuelve una promesa que se resolverá una vez que haya transcurrido ese retraso. Y lo que puedes ver aquí es básicamente esto es solo un envoltorio alrededor de setTimeout. De acuerdo. Entonces, sí. Cada vez que llamas a la función no bloqueante, en primer lugar obtienes una promesa. Puedes asignar esto a una variable, puedes usar p1 igual a eso. Y luego p1.then, blah, blah, blah. En primer lugar, obtienes una promesa. Y una promesa es un objeto que representa alguna operación asíncrona no bloqueante que producirá un valor, se resolverá a un valor o se rechazará con un error. Y esta función devuelve la nueva promesa y el cuerpo de la promesa llama a setTimeout para llamar a esta función a su vez. Esto se vuelve un poco complicado pero espero que todos puedan seguirlo. Básicamente, esto llamará a resolve con algún valor una vez que haya pasado el retraso. Genial, si solo tenemos una devolución de llamada el valor de usar promesas no es tan evidente pero espero que puedas ver aquí que estoy usando el método then en la promesa. Esto en realidad me permite, en primer lugar, esta sería la primera pauta de programación asíncrona de la que quiero hablar. Me permite secuenciar ejecuciones de devoluciones de llamada que ocurrirán, como se garantiza que la primera se llamará luego la segunda, luego la tercera en un orden específico. Entonces, si hago esto return 33, por ejemplo, lo que tenga sentido, luego puedo llamar con otro, ups, con otro valor, ups, no puedo escribir hoy, lo siento. Así. Y espero que puedas ver que lo que then hace es devolver otra promesa. Así que lo que estamos viendo aquí es que estoy activando alguna operación con una operación no bloqueante, y estoy describiendo una secuencia de cosas que deben suceder y gracias a la API de promesas, tengo la garantía de que todas estas llamadas sucederán en orden independientemente de cuándo se resuelva esta primera promesa. Y probablemente uno no escribiría esto así. Uno usaría el encadenamiento de devoluciones de llamada como esto, que podría ser más agradable para algunos. Pero sí, si ejecuto esto, si esto es la parte cuatro, cuando ocurre el retraso, y luego se ejecuta esto, y luego se ejecuta esto. Y otra cosa interesante sobre el encadenamiento de devoluciones de llamada en Promesa es que la devolución de llamada que se ejecuta en cada momento obtiene el valor de la devolución de llamada anterior. Como el valor que la devolución de llamada anterior está devolviendo. De esta manera, lo que estás definiendo aquí es casi como una tubería funcional de funciones que comienzan con algún valor y lo pasan, hacen algo con ese valor y pasan un nuevo valor al siguiente paso en la cadena. Por lo tanto, cuando llamas a una función no bloqueante con un uno, la Promesa se resuelve con ese valor. Entonces obtienes un uno aquí, y luego devuelves algo más. Y el siguiente paso lo obtiene a su vez. Y luego puedes seguir devolviendo nuevas cosas en la cadena para describir la operación que estás intentando hacer aquí. Y nuevamente, esto te permite descomponer los efectos secundarios en fragmentos más pequeños. Y esto te permite describir el orden en el que estas cosas deben suceder. ¿Cuándo se ejecutará delayedSeconds, no entiendo esto, sí, lo siento, sí, esto, tal vez la notación no ayuda a entender las cosas, lo siento. Escribamos esto de manera ligeramente diferente, ¿de acuerdo? Porque estoy introduciendo una función, ups, ups.

20. Ajustando las Devoluciones de Llamada e Introduciendo Promise.all

Short description:

Aquí estoy introduciendo cómo ajustar las devoluciones de llamada. Esto te permite describir el orden, te permite descomponer los efectos secundarios en fragmentos más pequeños. Cada vez que llamas a 'then', puedes proporcionar dos devoluciones de llamada diferentes. Una se ejecutará si la promesa anterior se resuelve y otra se ejecutará si la promesa anterior es rechazada con un error. Esto se usa a menudo para gestionar errores. Otra cosa que puedes hacer aquí es usar 'catch'. Además de poder llamar a 'then', también puedes llamar a 'catch' al final. Esta es una llamada de terminación. Si tienes una devolución de llamada de error aquí y devuelves, por ejemplo, 33, volverás al flujo de éxito y 'catch' no se llamará. El primer patrón de diseño se trata de la operación síncrona, la secuenciación de devoluciones de llamada. En la parte cinco, en el siguiente archivo, tienes otro patrón de diseño de programación asíncrona que se llama semáforo. Y esto se proporciona mediante 'promise.all'. Y luego proporcionas una matriz de promesas.

De acuerdo. ¿Está bien? Veamos, ahí tienes. Genial, ¿recuerdas que hicimos esto aquí? 'SetTimeout' con una función y un retraso. Básicamente, esto es lo mismo, ups, ups. ¿Dónde se fueron, lo siento? Esto es lo mismo aquí. El mismo código. El retraso en segundos por 1000 básicamente me permite decir un segundo, dos segundos, y esto es lo que se va a pasar, ¿de acuerdo? Así que eso, sí, genial. Bien. Sí, como resumen, aquí estoy introduciendo cómo ajustar las devoluciones de llamada. Esto te permite describir el orden, te permite descomponer los efectos secundarios en fragmentos más pequeños. Y tienes la garantía de que esto no se llamará antes de que esto se complete. Otra cosa que esto nos proporciona es, por ejemplo, si escribo esto así, en realidad puedo hacer esto, ups, error de consola, oh, lo siento. Para mantener las cosas simples, no hice esto antes, pero cada vez que llamas a 'then', en realidad puedes proporcionar dos devoluciones de llamada diferentes. Una se ejecutará si la promesa anterior se resuelve y otra se ejecutará si la promesa anterior es rechazada con un error. Y esto se usa a menudo para gestionar errores, ¿verdad? Y harías cosas como registrar el error así o tal vez puedes devolver algún valor predeterminado. Ya sabes, ese tipo de valores predeterminados que podrías elegir devolver en caso de que algo salga mal. Y esto, lo que estamos haciendo efectivamente, es que esta promesa fue rechazada, ¿verdad? Y luego se llamó a esta devolución de llamada. Entonces, al devolver algo aquí, lo que estamos haciendo efectivamente es recuperar el flujo de la promesa hacia el flujo de éxito. Como si hubiéramos ido al camino del error porque algo fue rechazado, pero al devolver algo, estamos forzando el flujo de vuelta al flujo de resolución. Para continuar, ya sabes, ejecutando el cambio de efectos secundarios a través del flujo de éxito, lo que sea. Otra cosa que puedes hacer aquí es usar 'catch'. ¿Qué sucede si proporcionas otra función y también 'catch' al final? De acuerdo, eso es lo que voy a hacer. Así que el 'catch', 'catch', uno así, ¿qué está pasando? De acuerdo, tú, además de poder llamar a 'then', también puedes llamar a 'catch' al final. Y esto es lo que se llama, bueno, no estoy seguro si este es el nombre preciso, pero esta es una llamada de terminación. Como que no puedes ir a 'then' después de llamar a 'catch', ¿de acuerdo? Esto termina la cadena de efectos secundarios. Y esto te permite hacer una gestión final de errores. Como si no tuvieras ninguna devolución de llamada de error, no es necesario proporcionar una devolución de llamada de error, esto es opcional. Por lo tanto, solo podrías obtener el flujo del camino del éxito de esa manera. Y luego escribir el 'catch' aquí al final. Y esto se ejecutará, independientemente de lo que haya fallado, de lo que haya sido rechazado. Ahí lo tienes. Esa es una mejor explicación. Gracias. Genial. Así que el primer patrón de diseño se trata de la operación síncrona, la secuenciación de devoluciones de llamada. Ahí tienes el 'then', y el 'catch', y las devoluciones de llamada de resolución, y las devoluciones de llamada de rechazo. Puedes gestionar errores de una manera muy estructurada, súper útil. En la parte cinco, en el siguiente archivo, tienes otro patrón de diseño de programación asíncrona que se llama semáforo. Y esto se proporciona mediante 'promise.all'. Y luego proporcionas una matriz de promesas.

21. Entendiendo Semáforos y el Patrón de Carrera

Short description:

Esto se llama un semáforo, que es una promesa que se resolverá cuando todas las promesas se hayan completado. Garantiza un orden específico de valores y elimina la incertidumbre en las operaciones asíncronas. Otro patrón útil es la carrera, donde las promesas compiten entre sí y se llama a la devolución de llamada con el valor de la primera promesa resuelta o rechazada. El programa aún espera la finalización de las otras promesas, incluso si una ya se ha ejecutado. La implementación de promesas es compleja y hay matices y casos que pueden complicarla aún más.

Esto se trata solo de objetos y programación asíncrona. No voy a hablar de ningún motor de vista ni nada por el estilo. No te preocupes. Genial.

Entonces, nuevamente, esto se llama un semáforo. Lo llamas usando los métodos antiguos en el tema de las promesas y debes proporcionar una matriz de promesas. Y lo que esto hará, esto te dará una nueva promesa, P1. Y lo que estamos tratando de describir aquí es que P1 es una promesa que se resolverá o rechazará. Bueno, resuelta tal vez, es mejor. Cuando todas las promesas se hayan completado. Cuando todas las promesas se hayan resuelto. Y solo entonces, se ejecutará el siguiente efecto secundario, se llamará la siguiente devolución de llamada. Si estuviéramos en este ejemplo, uno, dos, tres, boom. Y obtienes la devolución de llamada llamada.

Y nota un par de cosas aquí. En primer lugar, esta promesa tarda un segundo en ejecutarse. Este es uno, dos y este es tres. Dado que estoy esperando a que se completen todos, este tomará al menos tanto tiempo como el más bajo de todos ellos, ¿verdad? Y la segunda cosa a tener en cuenta aquí es que la devolución de llamada aquí de P1, los argumentos de esta devolución de llamada serán una matriz de valores, y cada valor en esa matriz será el valor parcial de cada una de las promesas que componen el semáforo. Así que obtienes uno, dos, tres. En orden dos, no, si hiciera el orden opuesto. Bueno, esto está formateando el código de una manera diferente, pero sí. Estoy estableciendo en un orden diferente, ¿verdad? Tres, dos, uno. Si lo ejecuto de nuevo, obtendré tres, dos, uno. No se trata de quién es más rápido ni nada por el estilo. Se trata de garantizar que haya alguna relación entre la forma en que escribo el código y el orden en que obtengo las cosas aquí como valores. Esto es súper útil porque elimina mucha incertidumbre de una operación asíncrona que siempre es difícil de razonar. Esto te permite describir las cosas de una manera muy precisa, de una manera explícita. Así que ahí lo tienes. Esto se llama el semáforo. Lo llamas con Promise.All y te da una nueva promesa que se resolverá una vez que todas las promesas que la componen se resuelvan. Por lo tanto, será tan lento como el más lento de ellos. Genial. El siguiente, el mismo patrón que quería mencionar es la carrera y esto es súper útil. Espero que puedas ver esto al final de la, de mostrar esto alrededor. La carrera te permite literalmente competir un par de, un conjunto de promesas entre sí. Y lo que esto hace básicamente es que la devolución de llamada se llamará con el valor de la primera promesa que se resuelva o se rechace. Um, dado que estoy ejecutando uno, dos, tres, uno va a ganar, por supuesto, y luego uno se ejecuta allí. Y luego el programa aún necesita esperar la finalización de estas dos llamadas porque estas están desencolando cosas en la cola. De acuerdo, alguien está diciendo algo en el chat. De acuerdo, y lo siento, pero sobre la descripción de catch sobre si el controlador de resolución de la primera promesa lanza, no solo la primera función de error, también se llamará a catch. Sí, por supuesto, sí. Como dije al principio, hay muchos matices en juego. Y en realidad, la implementación de promesas es profundamente compleja. Hay, como, sí, una vez intenté implementar un motor de promesas y es, como, lo básico que llegas a entender y es intuitivo, pero puede volverse realmente complicado, realmente, realmente rápido. Pero sí, hay casos en los que, incluso si tienes un controlador de rechazo, blah, blah, blah. Puede volverse realmente complicado. Lo siento, pero sí, no hay mucho tiempo para profundizar en eso. Volviendo a la carrera aquí, lo que ves aquí es que aunque las promesas se resuelven muy rápido, como después de un segundo, el programa tarda un poco más en completarse y eso se debe a que estas dos llamadas aquí aún tienen que encolar cosas y esas instrucciones deben ejecutarse. Entonces eso significa que el programa en sí tomará tres segundos esperando a que se complete este uno, incluso si la llamada que fue hace dos segundos se ejecutó. Por eso estamos viendo el retraso aquí después de que se imprime el uno.

QnA

Implementando Timeouts con Promesas

Short description:

Y este es un patrón de diseño realmente útil porque te permite implementar timeouts. Si definimos una función llamada timeout, podemos crear una carrera entre un timeout y una función no bloqueante. Los timeouts pueden implementarse utilizando promesas y el método 'race' se puede utilizar para determinar qué promesa gana. El método 'any' es similar a 'race', pero espera a que cualquier promesa se resuelva antes de rechazar la promesa completa. Esto concluye el contenido del masterclass. Si hay alguna pregunta o fragmento de código que te gustaría discutir, no dudes en preguntar. ¡Gracias a todos por asistir!

Y este es un patrón de diseño realmente útil porque te permite implementar timeouts. Básicamente, un timeout, ¿qué es un timeout, verdad? Un timeout es una carrera entre una promesa que será rechazada después de cierto tiempo y tu lógica real que necesitas ejecutar. Entonces, si definimos una función AC llamada timeout con un retraso en segundos, y este es básicamente el mismo código que tenemos aquí, pero en lugar de llamar a resolve, llamamos a reject después de unos segundos. Y hacemos un timeout después de un segundo. Lo siento, pero esto está formateando el código cada vez que digo, pero sí, si hago una carrera entre un timeout que se agotará después de un segundo y la función no bloqueante que tarda dos segundos en ejecutarse, el timeout va a ganar y se va por la ruta de error. Si invierto el tiempo para que resulte que hay dos segundos pero la lógica real tarda un segundo en completarse, la lógica gana y sí, no hay timeout. Básicamente, así es como se implementan los timeouts y si, ya sabes, la herramienta que estás usando no te permite definir un timeout de una manera agradable pero funciona con promesas, puedes usar RACE para eso. Puedes tener timeouts en cualquier proceso que sea. Y el último, el mismo patrón y estoy agregando esto solo porque está ahí, está disponible en promise. Esto, el método any aquí y esto es básicamente lo mismo. Esto es RACE pero en este caso, el any seguirá esperando, si tengo el timeout nuevamente, lo copiaré aquí y hago un timeout después de un segundo, luego hago un timeout después de dos segundos y aún así esto se ejecutará correctamente. Esperará en caso de que alguna de las promesas se resuelva antes de, ya sabes, rechazar la promesa completa. Entonces, si lo ejecuto, sí, en segundo plano, el timeout comenzó a rechazar la promesa, pero como esto funcionó, obtenemos el tres. Y luego sí, esto es muy similar a nuestra carrera aquí. Y sí, básicamente estos son los contenidos que quería repasar. Hemos terminado con los contenidos y solo quedan siete minutos de las dos horas máximas. Así que estoy realmente contento con eso. ¿Tienen alguna pregunta antes de que terminemos el masterclass? ¿O tal vez pueden copiar y pegar algún fragmento de código en el chat, podemos analizarlo juntos o algo así. Sí, tienes razón Bjorn. ¿Dos minutos antes, verdad? ¿En serio? De acuerdo. De nada. Gracias a todos por venir, supongo. Estoy realmente contento de que tanta gente se haya unido, y sí, 39 todavía están aquí, así que felicidades. Gracias a todos por venir, de verdad. Estoy realmente contento de que tanta gente se haya quedado hasta el final, son mis héroes. Y también, si alguien tiene alguna pregunta, en cualquier momento, estoy en Twitter, y también puedes contactarme en Github. Ese es mi nombre de usuario en Twitter, solo envíame un mensaje. Estaré muy feliz de responder o intentar ayudarte de cualquier manera que pueda. Y nuevamente, trabajo en TSN Simple, somos un equipo pequeño, estamos buscando más personas para unirse a nosotros, así que asegúrate de revisar nuestra página de empleos si estás en el mercado. ¿Por qué usaste la sintaxis de Promise en lugar de async await? Oh, esa es una muy buena pregunta. Vamos a responder eso. Genial, async await es esta cosa que estoy usando aquí. Entonces, el asunto es que si uso async antes de una función, me veo obligado a devolver una promesa. Como esa función, estoy dando pistas al lenguaje. De acuerdo, responderé eso más tarde, Khalil. Ya tenemos un par de preguntas. Esto es genial. Entonces, ahora se me exige devolver una promesa porque usé async, ¿verdad? Entonces, lo que obtengo al hacer esto es que puedo, bueno, esto no tiene mucho sentido, pero de todos modos, ahora puedo esperar lo no bloqueante de lo que sea, comencemos un nuevo ejemplo porque esto se está complicando, ¿de acuerdo? De acuerdo, así que definamos una función, una función síncrona que se llama, bueno, llamémosla foo con algún valor y un retraso, y esto va a devolver una nueva promesa que se resuelve con un setTimeout y devuelve el valor, básicamente repite el valor que proporcionas después de cierto retraso, ¿de acuerdo? Entonces puedes llamar a foo con 42 después de 1000 milisegundos, obtienes el valor y esto debería mostrar en la consola 42, ¿verdad? Después de un segundo, probémoslo rápidamente. Ahí lo tienes, está funcionando, ¿verdad? Entonces, ya que usé async aquí, lo que puedo hacer en lugar de usar esta sintaxis aquí, en realidad puedo asignar el valor de llamar a foo. Si llamo a foo dentro de un await delante de él, ¿verdad?, y esto no va a funcionar. Primero necesito hacer algunos ajustes, esto se quejará porque no puedes usar await en una función que no es async. Como este es nuestro requisito. Entonces voy a envolver todo en una función llamada run, que es async, ¿de acuerdo? Y luego voy a llamar a run por ahora. Siempre devuelve una promesa independientemente del valor de retorno, el punto es esperar el resultado, no tanto cuando lo envolvemos con una promesa siempre. Oh sí, gracias. Me estoy moviendo hacia eso. Sí, primero necesito establecer la base. Como funciona, ¿verdad? Necesitas esperar y luego puedes asignar cualquier valor que desees.

Reemplazando Promise All y Uso de Balanceador de Carga

Short description:

Y luego lo que están sugiriendo aquí es que básicamente podría reemplazar la llamada a promise all con una secuencia de llamadas then. Esta sintaxis es mucho más simple y se puede utilizar si no necesitas que todas las operaciones se ejecuten al mismo tiempo. Sin embargo, es importante entender que esto no es equivalente a la llamada a promise all. En cuanto al uso de un balanceador de carga a nivel de aplicación como PM2 en producción con Node, depende del problema específico que estés tratando de resolver. Si estás soportando una aplicación web, el modelo de un solo hilo de Node.js se adapta bien. Sin embargo, para otros escenarios con múltiples procesos, se necesita una exploración más profunda. En cuanto a trabajos intensivos en CPU en Node, requiere un análisis cuidadoso e instrumentación de tu solución para determinar si el problema es realmente una ineficiencia. Puede haber problemas más simples o enfoques alternativos a considerar.

Y luego lo que están sugiriendo aquí es que básicamente, ¿por qué no simplemente hacer algo como valor uno, pondría valor dos. Oops, estoy contento de lo siento. Y valor tres, y esto es no sé, 41, 42, 43, por ejemplo. ¿Verdad? Y esto básicamente reemplaza el promise all, ¿verdad? Porque estoy esperando efectivamente a que todas las promesas se resuelvan. Y si ejecuto esto, debería, bueno, hagamos una demora muy rápida para no tener que esperar tanto. Como esto nos está dando casi lo mismo, ¿verdad? Aunque no es exactamente lo mismo, porque esto ejecuta esto, esperando a que se complete. Y luego ejecuta esto, esperando a que se complete y luego ejecuta esto. Y si estas son tres operaciones de entrada/salida, realmente no estamos permitiendo que el sistema operativo subyacente las maneje de la mejor manera posible. No estamos indicando a nuestro programa que lance las tres operaciones y espere a que todas se completen. Es decir, esto no es, esto no es equivalente a la llamada a promise all. Esto sería equivalente a then, punto then, punto then, punto then en secuencia, ¿verdad? Esa es la primera diferencia que tenemos. No sé si no puedes esperar más de una cosa, tal vez haya una forma de hacer eso como lo harías en una llamada a promise all de todos modos. Y la forma de manejar los timeouts, no estoy seguro, realmente. No he jugado mucho con esto para darte una mejor explicación en este momento, pero sí, espero que esto tenga sentido. Esto también es una sintaxis mucho más agradable, diría yo, como usar then y then, si puedes modelar tu programa de esa manera, es muy bueno. Y tal vez no te importe que estas tres operaciones se ejecuten al mismo tiempo o sean gestionadas por el sistema operativo, tal vez esto sea suficiente para ti. Y luego la sintaxis es mucho más simple, ¿verdad? Sí. Ba-do-ba-do.

Bueno, ¿esto parece cierto? Si toddler devuelve una promesa o un valor de retorno, que apunta, sí, ahí lo tienes. ¿Qué opinas de usar algún tipo de balanceador de carga a nivel de aplicación como PM2 en producción con Node, ya que es de un solo hilo? ¿Crees que es obligatorio para obtener todos los beneficios de la máquina? No lo sé, eso realmente depende de tu, sí. Lo siento, estoy respondiendo, no sé mucho. Realmente se trata del problema específico que estás tratando de resolver. Argumentaría que si, por ejemplo, solo estás soportando una aplicación web, el motor web, tal vez sean motores o lo que sea, va a generar un hilo para ti. Y este modelo de tener solo un hilo y una cola se ajusta muy bien dentro de ese modelo de ejecución. Si estás haciendo algo más, entonces necesitas explorar otras opciones. No tengo experiencia trabajando con sistemas de nodeJS que tienen muchos procesos, ya sabes, trabajando al mismo tiempo y obteniendo, sí, ese es un escenario que no he explorado. Lo siento, no puedo darte respuestas específicas. Y luego Kadir, también preguntaste, ¿cómo resolverías cuando de repente necesitas un trabajo intensivo en CPU en Node? Bueno, no lo sé. Lo siento. Lo siento, no lo sé. Esto es realmente algo en lo que necesitas, como, esto es algo advanced. Necesitas prestar mucha atención a la instrumentación de tu solución. Ser capaz de analizar tu programa a su vez para que sepas que ese es realmente tu problema. Tal vez haya otro problema más simple o tal vez algo que puedas, sí.

Bueno, espero haber respondido tu pregunta de alguna manera, ¿hay alguna otra pregunta? De lo contrario, creo que puedes dar por terminado el día. Gracias a todos por venir aquí de nuevo. Y supongo que debo detener la grabación o hacer algo más como anfitrión. Así que voy a hacer eso. Gracias a todos por venir de nuevo, realmente me alegró ver a tanta gente quedarse hasta el final. Y sí, disfruten del Congreso, por cierto. Nos vemos, gracias, adiós adiós.

Watch more workshops on topic

React Day Berlin 2022React Day Berlin 2022
86 min
Using CodeMirror to Build a JavaScript Editor with Linting and AutoComplete
Top Content
WorkshopFree
Using a library might seem easy at first glance, but how do you choose the right library? How do you upgrade an existing one? And how do you wade through the documentation to find what you want?
In this workshop, we’ll discuss all these finer points while going through a general example of building a code editor using CodeMirror in React. All while sharing some of the nuances our team learned about using this library and some problems we encountered.
Node Congress 2023Node Congress 2023
109 min
Node.js Masterclass
Workshop
Have you ever struggled with designing and structuring your Node.js applications? Building applications that are well organised, testable and extendable is not always easy. It can often turn out to be a lot more complicated than you expect it to be. In this live event Matteo will show you how he builds Node.js applications from scratch. You’ll learn how he approaches application design, and the philosophies that he applies to create modular, maintainable and effective applications.

Level: intermediate
TestJS Summit - January, 2021TestJS Summit - January, 2021
173 min
Testing Web Applications Using Cypress
WorkshopFree
This workshop will teach you the basics of writing useful end-to-end tests using Cypress Test Runner.
We will cover writing tests, covering every application feature, structuring tests, intercepting network requests, and setting up the backend data.
Anyone who knows JavaScript programming language and has NPM installed would be able to follow along.
Node Congress 2023Node Congress 2023
63 min
0 to Auth in an Hour Using NodeJS SDK
WorkshopFree
Passwordless authentication may seem complex, but it is simple to add it to any app using the right tool.
We will enhance a full-stack JS application (Node.JS backend + React frontend) to authenticate users with OAuth (social login) and One Time Passwords (email), including:- User authentication - Managing user interactions, returning session / refresh JWTs- Session management and validation - Storing the session for subsequent client requests, validating / refreshing sessions
At the end of the workshop, we will also touch on another approach to code authentication using frontend Descope Flows (drag-and-drop workflows), while keeping only session validation in the backend. With this, we will also show how easy it is to enable biometrics and other passwordless authentication methods.
Table of contents- A quick intro to core authentication concepts- Coding- Why passwordless matters
Prerequisites- IDE for your choice- Node 18 or higher
JSNation 2023JSNation 2023
104 min
Build and Deploy a Backend With Fastify & Platformatic
WorkshopFree
Platformatic allows you to rapidly develop GraphQL and REST APIs with minimal effort. The best part is that it also allows you to unleash the full potential of Node.js and Fastify whenever you need to. You can fully customise a Platformatic application by writing your own additional features and plugins. In the workshop, we’ll cover both our Open Source modules and our Cloud offering:- Platformatic OSS (open-source software) — Tools and libraries for rapidly building robust applications with Node.js (https://oss.platformatic.dev/).- Platformatic Cloud (currently in beta) — Our hosting platform that includes features such as preview apps, built-in metrics and integration with your Git flow (https://platformatic.dev/). 
In this workshop you'll learn how to develop APIs with Fastify and deploy them to the Platformatic Cloud.
JSNation Live 2021JSNation Live 2021
156 min
Building a Hyper Fast Web Server with Deno
WorkshopFree
Deno 1.9 introduced a new web server API that takes advantage of Hyper, a fast and correct HTTP implementation for Rust. Using this API instead of the std/http implementation increases performance and provides support for HTTP2. In this workshop, learn how to create a web server utilizing Hyper under the hood and boost the performance for your web apps.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

Remix Conf Europe 2022Remix Conf Europe 2022
23 min
Scaling Up with Remix and Micro Frontends
Top Content
Do you have a large product built by many teams? Are you struggling to release often? Did your frontend turn into a massive unmaintainable monolith? If, like me, you’ve answered yes to any of those questions, this talk is for you! I’ll show you exactly how you can build a micro frontend architecture with Remix to solve those challenges.
Remix Conf Europe 2022Remix Conf Europe 2022
37 min
Full Stack Components
Top Content
Remix is a web framework that gives you the simple mental model of a Multi-Page App (MPA) but the power and capabilities of a Single-Page App (SPA). One of the big challenges of SPAs is network management resulting in a great deal of indirection and buggy code. This is especially noticeable in application state which Remix completely eliminates, but it's also an issue in individual components that communicate with a single-purpose backend endpoint (like a combobox search for example).
In this talk, Kent will demonstrate how Remix enables you to build complex UI components that are connected to a backend in the simplest and most powerful way you've ever seen. Leaving you time to chill with your family or whatever else you do for fun.
JSNation Live 2021JSNation Live 2021
29 min
Making JavaScript on WebAssembly Fast
Top Content
JavaScript in the browser runs many times faster than it did two decades ago. And that happened because the browser vendors spent that time working on intensive performance optimizations in their JavaScript engines.Because of this optimization work, JavaScript is now running in many places besides the browser. But there are still some environments where the JS engines can’t apply those optimizations in the right way to make things fast.We’re working to solve this, beginning a whole new wave of JavaScript optimization work. We’re improving JavaScript performance for entirely different environments, where different rules apply. And this is possible because of WebAssembly. In this talk, I'll explain how this all works and what's coming next.
React Summit 2023React Summit 2023
24 min
Debugging JS
As developers, we spend much of our time debugging apps - often code we didn't even write. Sadly, few developers have ever been taught how to approach debugging - it's something most of us learn through painful experience.  The good news is you _can_ learn how to debug effectively, and there's several key techniques and tools you can use for debugging JS and React apps.
Node Congress 2022Node Congress 2022
26 min
It's a Jungle Out There: What's Really Going on Inside Your Node_Modules Folder
Top Content
Do you know what’s really going on in your node_modules folder? Software supply chain attacks have exploded over the past 12 months and they’re only accelerating in 2022 and beyond. We’ll dive into examples of recent supply chain attacks and what concrete steps you can take to protect your team from this emerging threat.
You can check the slides for Feross' talk here.