This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Hoy vamos a hacer una prueba técnica real, real porque está basada en una empresa de aquí de España,
justamente de Barcelona, pero no voy a decir exactamente la empresa porque alguna vez he mencionado empresas
y me escribe gente de la empresa. Me ha escrito gente y hay gente, pues hay gente que a lo mejor no le ha gustado
las cosas que hemos hecho. Entonces tampoco me parece muy importante, me parece muy interesante, sinceramente,
la empresa en concreto, pero sí que les voy a contar el rango de salario que es, qué es lo que se espera de la prueba
y vamos a revisar la prueba. La tengo aquí, ¿vale? Prueba técnica, JavaScript, no GS. Escribe las soluciones, bla, bla, bla,
y es bastante larguita, ¿vale? Entonces, les comento cosas. Yo la he adaptado, la he adaptado para que no sea exactamente igual,
pero he intentado que sea el mismo espíritu. ¿Qué quiere decir esto? Pues que hay ejercicios en esta empresa
que las hacen de una forma y yo lo he cambiado y he hecho otra cosa, pero con la misma idea de lo que se quiere buscar
o lo que yo entiendo que se quiere buscar en la prueba técnica, ¿vale? Y son más de un ejercicio. ¿Por qué?
Y les voy a explicar. Es una prueba que dura aproximadamente dos horas, dos horas, y se hace en live coding.
E incluso tiene una parte de pizarra. Ya sabéis mi opinión de las pizarras, hay muchas empresas que lo hacen, es lo que hay.
O sea, yo no es una prueba que a mí me encante particularmente, que diga, no, me encanta. Pero es la realidad, es lo que hay.
O sea, te estoy trayendo una prueba que sé que la hacen así, que es exactamente así, y que está bien que te la prepares justamente
pues para que entiendas qué es lo que esperan que contestes, cómo lo tienes que hacer, cómo tienes que ir iterándola y todo esto.
A mí me parece una prueba que es dura, porque son dos horas y normalmente dos horas pues uno acaba con la cabeza frita.
Pero amigos, en la realidad hay empresas, al menos aquí alrededor de España, ¿vale?
En Barcelona concretamente, que hacen este tipo de pruebas.
Es con live coding y con pizarra. O sea, que hacen una parte de live coding que tú tienes que programar
y tienes unos cuantos ejercicios y además tienes que explicar, ya sea haciendo algún tipo de posgráfico o lo que sea
para intentar decirle por qué funciona esto así, esto asá y tal.
O incluso te hacen cosas en la pizarra como para que lo expliques.
Live coding respirándote en la nuca, ¿qué tensión?
Bueno, tengo entendido que en esta empresa no te respiran en la nuca.
El live coding, para que no lo sepa, es hacer pruebas de código en la que estás programando en tiempo real.
O sea, te están viendo. Y hay diferentes formas de hacerlo y en esta empresa tengo entendido que sí que te ayudan.
O sea, no te están respirando en la nuca y están en un silencio tenso y escuchan la respiración,
sino que te van ayudando si te quedas y tal.
Porque esto es una prueba técnica que es de Junior C-Training.
De hecho, vamos a comentar cuál es el salario.
Esta prueba técnica de JavaScript y Node.js, ¿vale?
El puesto es para Junior Frontend, ¿vale?
Y la idea es que toques JavaScript, JavaScript Frontend Vanilla, más algo de Node.js.
Esta es la idea del puesto de trabajo.
La empresa, no os voy a decir qué empresa es, pero os voy a decir de qué van.
Y hablan de temas, temas, ¿cómo diría?
Análisis de datos, monitorizaciones, procesamiento de datos, ¿vale?
Esta es la idea, el sector de la empresa, ¿vale?
Análisis de datos, monitorizaciones, procesamiento de datos, etc.
De eso va la empresa, ¿vale?
¿De dónde es?
Es de España, Barcelona.
Si queréis, podéis buscar, ¿vale?
De más o menos por el sector os podéis imaginar unas cuantas.
¿Y cuál es el rango salarial?
El rango salarial de esta oferta no es 18 tal, sino que tengo entendido que son 19.500 a 22.000 euros al año, ¿vale?
Al año.
Entonces, no es el mejor sueldo del mundo, ¿vale?
No es la empresa que mejor paga de Barcelona.
Entonces, sí, ¿verdad?
Una miseria.
La verdad, lo siento.
Normalmente, el rango salarial, normalmente rango de Barcelona, debe estar, que no significa que la gente no esté por aquí,
un buen rango debería ser de 20 a 24.
Un buen rango, ¿vale?
Buen rango.
Las cosas como son.
Ahora, habrá gente que me dirá, pues yo gano menos y tal, y seguro que tienes razón, ¿vale?
Pero yo digo lo que yo considero que es un buen rango en Barcelona, en España, porque es que si no...
Para empezar, como junior trainee, ¿eh?
Para que la gente lo tenga claro, junior, una persona con poca experiencia, pero con experiencia, ¿vale?
Esto puede ser, pues, de cero a dos años, más o menos.
Y luego, trainee, persona sin experiencia, pero con conocimientos, ¿ok?
Que son dos cosas diferentes.
Lo digo para que ya lo tengáis todo claro.
Resumen de la prueba técnica.
Hoy hacemos una prueba técnica de JavaScript y Node.js desde cero.
Y son unos siete ejercicios que tenéis que completar.
Son ejercicios cortos, pequeños, rápidos de hacer, sobre todo si sabe lo que hay que hacer, ¿no?
En el primer ejercicio hay que arreglar una función, ¿vale?
Para que haga lo que se le espera.
Para que entendáis lo que está haciendo exactamente la función.
La segunda, hay que transformar una función para que funcione con promesas en lugar de callbacks.
La tercera, hay que explicar qué hace una función, identificar errores y posibles mejoras de elegibilidad del código, ¿vale?
La cuarta, hay que mejorar un código, que obviamente está haciendo llamadas síncronas y tenemos que ver cómo podemos mejorar esto.
La cinco, es bastante sencilla, que es escribir una función delay, que devuelva una promesa, ¿vale?
Que se resuelva después de n milisegundos.
No os preocupéis que yo os estoy explicando cada ejercicio.
La seis, hay que crear tu propio .env, que es una biblioteca muy utilizada en Node.js, que a día de hoy ya no es tan interesante y tan importante,
pero que se puede hacer en un momentito, ¿vale?
Sobre todo si sabes hacerlo.
O aquí, y esto luego lo explicaré, ¿vale?
Pero muchas veces en estos ejercicios no están esperando que hagas exactamente el 100%, sino para ver cómo lo piensas y cómo lo harías, ¿vale?
Nosotros lo vamos a intentar hacer lo mejor posible.
Y finalmente, la siete, que es hacer una API REST rapidita con Express.
Entonces, estos serían los siete ejercicios.
Antes de que os asustéis de que es mucho, es demasiado, no sé qué, os digo, son dos horas y además, por lo que tengo entendido,
porque yo no he hecho la prueba técnica, pero sí que la ha hecho alguien y me ha explicado cómo ha sido el proceso,
por lo que tengo entendido, te ayudan, ¿vale?
Y puedes mirar documentación en internet, puedes, tengo entendido que puedes utilizar herramientas de inteligencia artificial,
pero no Gihaco Pilot, o sea, puedes preguntar a una inteligencia artificial, pero no puedes utilizar Gihaco Pilot para que te haga el autocomplete.
Y eso, puedes mirar documentación y todo eso, o sea, puedes buscar en internet.
Yo me imagino, cuando dicen que puedes utilizar ChagPT, es que le puedes preguntar dudas concretas, ¿sabes?
No le puedes decir, arréglame esto, ¿vale?
Esto muchas veces lo hacen.
¿Cómo puedo crear una cosa en concreto?
Y eso sí que te dejan, pero no puedes preguntarle la solución al reto.
Para que tengáis la prueba técnica, vamos a subir esta prueba técnica aquí, la vamos a dejar aquí, ¿vale?
Porque estas dos son de frontend, de hecho, vamos a empezar a diferenciar las que son de frontend y las que son más de backend,
porque si os fijáis, esta prueba técnica en realidad no tiene absolutamente nada de frontend, ¿vale?
Sí que es JavaScript vanilla, es JavaScript más de palo, ¿no?
O sea, JavaScript sin ningún tipo de UI.
Y esto lo suelen hacer algunas empresas que no les interesa tanto que sepas del framework en concreto,
porque al final, si sabes de vanilla, pues no debería costar mucho.
Y aquí lo que miran mucho es que sepas asincronía.
Lo que esperan en esta prueba, si os fijáis, lo que esperan es esto que he puesto aquí.
Ejercicios de asincronía.
Que entendáis la sincronía.
Callbacks versus promises.
O sea, que sepáis promesas, callbacks, que sepáis crear una API desde cero, más o menos, ¿no?
Encontrar errores en el código, buenas prácticas y refactorización.
Y una cosa interesante de la prueba es que tienen test.
Eso es tan chulo.
O sea, la idea de la prueba, si no recuerdo mal, es que se ejecuten los test.
¿Sabes? Que los test funcionen.
Que todos los test funcionen.
Entonces, yo he creado los test también para que lo tengáis de prueba,
por si queréis hacerlo vosotros, ustedes, lo quieren hacer en su casa.
Esto lo subiré después en GitHub y entonces lo van a tener.
Y entonces estaría bastante bien.
Y le pueden intentar ejecutar los test y tal.
Eso está muy bien porque así, mientras vas haciendo la prueba, en vivo y en directo,
puedes ir probando si los ejercicios los has hecho bien o no los has hecho bien.
Dice Junior Frontend, pero parece más de backend.
Ay, es que he puesto Junior Frontend y no era Frontend.
Perdón, es Full Stack.
La idea, perdón, he puesto Frontend aquí y el perfil no es de Frontend.
Es de Full Stack.
Lo que esperan en esta empresa es que toques, por un lado, temas de backend que tienen en OGS
y temas de Frontend que lo tienen en un Vanilla.
Lo tienen con Vanilla.
O sea, no tienen ni React ni nada.
Sino que muestran los datos con Vanilla, JavaScript y con Web Components y todo esto.
Y lo que esperan es que sepas tocar las dos cosas.
Eso es lo que esperan.
Así que gracias por comentarlo porque no es de Frontend en Full Stack.
Arregla esta función para que el código posterior funcione como se espera.
Nos dan una función que parece que ya está hecha y tenemos que darnos cuenta cuáles son los problemas.
Esto está muy bien porque empezamos no teniendo que hacer nosotros el código,
que nos podemos poner nerviosos y ya nos dan un código en el que tenemos que visualizar.
Yo os voy a ir explicando lo que yo haría y algunas recomendaciones.
Lo primero, obviamente, miramos el código y ya lo copiamos donde nosotros vamos a trabajar.
Lo quitamos del Ritmi y si nos fijamos aquí pone,
escribe las soluciones en archivo Solutions Index,
manteniendo el nombre de las funciones y sus export.
Usa S-Modules en tu producto de Node.js.
O sea que tenemos que poner nuestras soluciones en solutions barra index.js.
Aquí.
Y aquí ya vamos a copiar y pegar el primer código.
Por cierto, voy a quitar GithackoPilot para que no me chive nada.
GithackoPilot.
Que si no luego me decís, no, es que esto con GithackoPilot.
Y como la prueba no se puede utilizar, pues nosotros tampoco lo utilizamos.
Lo que sí que os digo es que siempre que podáis, si es posible, que instaléis un linter.
El linter es la clave.
Primero, aquí ya se nota que fijaos que lo que nos está diciendo es que
arregla esta función para que el código posterior funcione como se espera.
O sea, hay que tener en cuenta una cosa.
Esto, uno, no funciona como se espera, ¿vale?
Dos, hay que arreglar algo.
Hay que arreglar algo.
Algún problema tiene.
Aquí normalmente nos ponemos de los nervios ya pensando en
Ay, ¿dónde está el error? ¿Qué pasa? No sé qué.
No lo veo, no lo veo, no lo veo.
Bueno, truco del almendruco.
Normalmente cuando te dice que una función no hace lo que se le espera,
lo primero que te tienes que fijar siempre es en los parámetros.
Lo primero, los parámetros.
Porque es donde normalmente está el error, el problema.
Normalmente.
Entonces, antes de ponerte a tal, si tienes que pensar en algo,
piensa en los parámetros.
Por ejemplo, lo primero que tendrías que ver es más bien esto.
Yo lo que haría sería olvidarme de la implementación, ¿vale?
Primero nos olvidamos de la implementación.
Me importa un pepino lo que haga, ¿vale?
Y lo que pienso es, vale, a ping le llega una IP, hace lo que tenga que hacer.
Pero fíjate aquí que ya ping, tenemos aquí una cadena de texto
y aquí le llega un callback.
Pam, en la frente, ¿vale?
Y es que normalmente cuando en un live coding te dicen
esto hace lo que esperas, no sé qué,
normalmente siempre te van a hacer una trampa de estas de parámetros.
No es el 100% de las veces, pero es una de las primeras cosas
que vas a poder revisar muy fácilmente, ¿vale?
Olvidarte de la implementación, que aquí vas a perder mucho tiempo
y el primer chequeo es como pam, pam, pam, muy rápido.
Otra cosa, ya que más o menos ya sabemos lo que tiene,
sería intentar si esto funciona.
Ya que tenemos el código que no hace lo que se espera,
una cosa que puedes intentar es decir, vale, pues lo voy a ejecutar.
Node index solutions index.js.
Nosotros ya sabemos lo que le pasa, ¿vale?
Pero fíjate que aquí no nos está dando ningún tipo de pista.
¿Por qué?
Porque se ejecuta, parece que no peta y por eso ya pensamos,
hostia, no sé qué pasa, qué está pasando y tal.
Entonces, por eso os digo primero los parámetros.
Y aquí hemos detectado que este callback no se está ejecutando, ¿vale?
Entonces, vamos a ver qué es lo que pasa aquí.
Lo que pasa aquí es que el callback, si ahora vamos a mirar la implementación,
¿qué es lo que se supone que hace?
Vale, aquí está tomando como el punto de inicio de la ejecución de este método.
Y luego aquí está creando un cliente.
No es importante tanto porque hay mucha gente que dirá,
ostras, no sé lo que hace.
Por ejemplo, puedes decir, es que no sé lo que hace la biblioteca net.
Justamente lo que buscan muchas veces estas empresas no es tanto que tú te sepas de memoria
lo que hace la biblioteca net o qué hace este connect y tal.
Ellos lo que quieren es a ver cómo te enfrentas a un código que te es desconocido.
Entonces, no hace falta, y esto te lo hace muchas veces,
no hace falta que te vuelvas ahí tan humba pensando,
ostras, yo no entiendo qué es este punto connect y tal.
Porque justamente lo que quieren es de algo que no te va a ser muy conocido,
cómo te puedes enfrentar a ello.
Entonces, siempre con la calma.
Entonces, aquí ya el ping.
Tengamos aquí la IP.
Lo importante, tanto si sabes JavaScript o no.js,
es el hecho de conocer los callbacks.
¿Qué son los callbacks?
Los callbacks son funciones que se ejecutan una vez que ha ocurrido algo.
Y lo que nos permite es, pues, cosas que sean asíncronas,
que ocurren de forma totalmente asíncrona,
podamos retomar el hilo de ejecución de nuestro programa.
Entonces, ¿qué pasa aquí en este ping?
Pues, fíjate que creamos un cliente y dice,
cuando se conecta en el puerto 80 y en la IP que le estamos pasando con parámetro,
aquí tenemos un callback y dice, vale, termina client end
y después devuelve el time process, no sé qué, no sé cuánto, ¿vale?
O sea, que hace como, aquí sería el start time
y aquí tendríamos el tiempo de finalización.
Y es como para ver cuánto tiempo ha pasado entre el inicio
y hasta que ha terminado la conexión, ¿vale?
Más o menos ya vamos entendiendo.
Y esto sería en el caso de que cuando conecta
y aquí cuando hay un error, pues, fíjate,
lanza el error y luego client.end.
Aquí, entonces, ya veo dos cosas, ¿no?
El primero, que como se está utilizando, no es lo mismo.
Aquí le faltaría, por ejemplo, el callback, ¿vale?
La función que es la que va a recuperar tanto si tiene un error
como si tiene una info y aquí vamos a poder revisar.
Si tiene un error, hago esto.
Si no tiene un error, hago console.log.info.
Aquí podríamos poner un else, no sé por qué sería así, pero bueno.
Si tiene un error, hago esto y si no, pues hago esto, ¿vale?
Y entonces, para poder utilizar este callback,
vamos a tener que ver dónde sería el sitio idóneo y correcto.
En este caso, es súper, súper típico que este return de aquí,
esto no funciona, ¿vale?
¿Por qué no funciona?
No funciona porque, fijaos, que este return es de esta función de aquí.
Por lo tanto, este return se queda ahí varado en la nada.
Este return no va a devolver, no va a llegar en este info.
Para hacer esto, ¿vale?
Lo que vamos a necesitar sería decir, vale,
en lugar de hacer un return, lo que necesitamos es ejecutar el callback
y pasarle la información.
Entonces, en lugar de hacer este return,
lo que tenemos que decir es, callback, ¿vale?
Primer parámetro, siempre es null, ¿vale?
Siempre es null porque, bueno, siempre es null en este caso.
Porque el primer parámetro en el callback siempre se le pasa el error.
Esto es un estilo de programación de Node.js,
pero también muchas veces en los callbacks funcionan así.
Luego vamos a ver que los callbacks no es la única forma de trabajar
porque hay otros ejercicios que te dicen,
que cambia el callback por promesas y lo vamos a conseguir.
Pero de forma clásica, Node.js se utilizan los callbacks.
El primer parámetro sería el error, que en este caso es null.
Y en el segundo parámetro tendríamos que pasar la información
que queremos devolver.
Fíjate que este callback es esto que pasamos aquí.
Mira, te voy a hacer un croquis.
Te voy a hacer un croquis.
Y es que por eso os digo que se utiliza pizarra.
Pues vamos, y esta función que veis aquí,
esta función es la que le está llegando aquí como callback, ¿vale?
Por lo tanto, aquí vemos que el primer parámetro es error, ¿vale?
Por lo tanto, este error que tenemos aquí es el que le pasamos aquí como null.
Y el segundo parámetro, que es info,
es lo que le estamos pasando aquí como un objeto, ¿vale?
Y ahí ya tendríamos el asunto.
Así que esto que le estamos pasando aquí como segundo parámetro
es la función que le llega aquí como callback, ¿vale?
Esto es lo primero.
O sea, ya al menos aquí tendríamos el callback si todo funciona bien.
Si guardamos los cambios, hacemos no solutions, ¿vale?
Veis que ahora sí que está funcionando como se le espera.
Pero hay trampa, hay trampa.
Y hay que tener cuidado con esto, ¿vale?
¿Los callbacks necesitan de async await?
Como puedes ver, no.
Los callbacks no necesitan de async await
porque como funciona justamente el async await
es una forma diferente de tratar la asincronía.
Callback era como utilizamos la asincronía,
como tratábamos la asincronía anteriormente.
Y lo que pasa en los callbacks es una función que se ejecuta
cuando haya ocurrido alguna cosa que pueda ser asincronía.
En este caso, lo que tenemos aquí, cuando se conecte,
entonces hacemos esto.
Así es como se traduciría un poquito el callback, ¿vale?
Esto os daría, yo creo que del punto os daría la mitad
porque ojo cuidado con pensar que ya habéis visto todo lo que tenía, ¿vale?
Lo que tenéis aquí, veis que hay un client punto error
y veis que esto está como medio que no se ve.
Esto es porque se ha detectado que este código es inaccesible.
Por lo tanto, tened cuidado de que tenga que estar ahí bien pila
porque aquí también hay otro error.
Y es que lo mismo que hemos hecho aquí con este callback
lo tenemos que hacer aquí.
Y tenemos que pasarle el error y además,
en lugar de hacer un throw que este throw tampoco no funciona,
esto no sirve para nada, ¿vale?
Tendríamos que eliminar el...
Tenemos que terminar la conexión del cliente.
Por eso lo podéis hacer antes incluso,
del callback y ya está.
Lo del error, no lo vamos a probar, ¿no?
Porque, bueno, lo podríamos forzar,
pero es importante que cuando trabajamos con callbacks,
si justamente ya tenía aquí lo del error, ¿vale?
Estar bastante atentos de que los errores también los tenéis que arreglar.
Y esto sí que ahora os daría como el punto,
yo creo que completo,
porque creo que esto es todo lo que esperaban en este ejercicio, ¿no?
Arregla esta función para que el código posterior funcione como se espera.
Ya lo hemos arreglado,
lo que hemos quitado es este return que no tenía ningún tipo de sentido
y este throw que tampoco tenía ningún sentido.
Estamos utilizando callbacks porque,
como se está utilizando esta función,
es como un callback con segundo parámetro
y fijaos que aquí le falta segundo parámetro, ¿vale?
¿Se puede decir que esa función callback es recursiva?
No, no es recursiva porque no se está ejecutando un callback
dentro del mismo callback.
Este callback es una función normal y corriente.
O sea, esta función es la que le está llegando aquí
y aquí se está llamando solo una vez.
No se está llamando de ninguna forma recursiva.
¿No deberías pasarle parámetro de info como null a callback?
En realidad no haría falta porque aquí ya le estaría llegando undefined directamente.
Y tiene sentido porque cuando no se le pasa el parámetro,
el parámetro va a llegar aquí como undefined.
Y tiene sentido que info sea undefined porque no está definido ese parámetro
porque no ha llegado absolutamente nada.
Pero hay veces que sí que hay gente que le pasa el null
como para saber exactamente que es null.
Lo podéis hacer de las dos formas, pero yo creo que en este caso no es necesario.
Aquí sí que es necesario porque fíjate que el error tiene que ser null
porque si no, ¿sabes? No podrías hacer esto.
Y podrías tener un error.
Con esto se supone que al menos algún test nos debería pasar.
Vamos a hacer no test.
Bueno, nos está petando, pero más por otro tipo de cosas.
A ver, vamos a...
Ah, puedo ejecutar los test de note barra test barra...
index.test.js, ¿vale?
Bueno, claro, es que me da errores de caer archivos que todavía no están...
Como están aquí todos los simpos y tal.
Vale, vamos a ver...
Los voy a separar, ping.test.js.
Y así, pues, vamos a ir viendo que van funcionando cada uno de los ejercicios,
al menos con el test que se supone que nos dan, ¿vale?
Así que tendríamos esto por aquí, esto por acá.
Vamos a ver si este funciona.
Describe.
Ponemos esto.
Y ahora, note test barra ping.test.js, ¿vale?
Y este ahora ya ha pasado, ¿vale?
Ya lo tenemos en verde.
Perfecto.
Ya tenemos el primero.
Esto funciona en Node.js, pero que sepáis que lo que estamos haciendo también funcionaría para Dino y para Bon, ¿vale?
Para que lo tengáis en los dos.
Importante, la versión de Node, os recomiendo que tengáis como mínimo la 18, que sería la LTS.
La LTS significa Long Term Support y la podéis tener aquí, ¿ves?
18.18.
Con que tengáis la 18, todo lo que veis ya funcionaría.
El primer ejercicio, arregla esta función.
Esto, check, ¿vale?
Así que vamos con la siguiente, a ver qué nos dicen.
Transforma la siguiente función para que funcione con promesas en lugar de callbacks.
Bueno, esto es una cosa que mucha gente se pone muy nerviosa.
Esta es bastante importante porque es súper típico.
Esto que vais a ver es súper, súper, súper típico, ¿vale?
Hay dos formas de hacerlo, lo cual es bastante interesante, pero hay una que es que tenéis que saber hacer, ¿ok?
Fijaos que tenemos aquí obtener datos promise, pero lo que está funcionando ahora es con un callback.
Lo que podemos hacer es transformar cualquier cosa que sea con callback, la podéis transformar para que funcione con promesas.
Y lo podéis hacer de dos formas, en realidad.
Lo podríais hacer, uno, utilizando el promesify este, promesify, promesify, promesify, promesify, ¿vale?
The node util, esto lo podríais intentar utilizar, no estaría mal del todo.
Y podríais, pues, crear aquí, obtener datos promise, haciendo así, obtener datos, vamos a poner algo así.
Podríais intentar hacer algo así, pero bueno, es un poco, claro, esto a lo mejor no lo van a aceptar porque van a decir, no, no, quiero que cambies cómo es la función y tal.
Bueno, pues vamos a hacerlo, vamos a quitar esto, pero bueno, solo para que sepas que existe esa posibilidad.
Lo que buscan aquí es básicamente que os carguéis este callback, ¿vale?
Que en lugar de pasarle una función por parámetro, es que sea con una promesa.
Así que, lo primero que hacemos es quitar el callback y entonces, ¿qué pasa con esto?
¿Qué pasa con esto? ¿Qué hacemos aquí?
Bueno, las promesas son objetos en JavaScript que tiene una clase constructora.
O sea, podéis construir una promesa y a partir de ahí, pues, envolverlo, envolver el código para que todo lo que envuelve sea una promesa.
Y vosotros le decís cuando se resuelve o cuando se rechaza esa promesa.
Entonces, imagínate este timeout, ¿no? Que aquí tenemos el callback y lo que pasa aquí es, cuando pasan dos segundos, este callback se ejecuta.
Mira, lo vamos a ver, ¿no? Vamos a poner aquí obtener datos promesa y le vamos a poner aquí, por ejemplo, claro, este callback en realidad va a recibir, se supone, el error y la info, ¿no?
Si ponemos aquí info, ¿qué va a ocurrir? Pues que cuando pasen dos segundos y ejecutamos este código, solutions, index.js,
lo que vamos a ver, ¿ves? Se queda vacío, pero después de dos segundos aparecen los datos importantes.
Vale, lo que vamos a querer es decir, vale, este callback que está haciendo esta información que cuando pasan dos segundos recibe esto,
lo vamos a querer transformar todo en una promesa para tratar la sincronía de una forma diferente.
Lo que tenemos que hacer es dejar de utilizar el callback y directamente devolver una nueva promesa.
Y aquí le tenemos que pasar otro callback, que se le llama así, que va a recibir, por un lado, cuando se resuelve y cuando se rechaza.
Aunque yo os digo que en este caso no necesitamos cuando se rechaza, solo cuando se resuelve, ¿vale?
Cuando se resuelve. ¿Y qué tenemos que hacer dentro? Pues pasar este setTimeout aquí, ¿vale?
Y ahora en lugar de utilizar el callback, lo que hacemos es utilizar el resolve.
Pero como lo queremos resolver, ya este null, que era el que trataba del error, ¿no?
Porque el callback tendríamos en el primer parámetro el error y en el segundo parámetro la información,
este null ya no lo necesitamos, sino que simplemente le pasamos que se resuelva con los datos que queremos.
Si tuviéramos algún error, tendríamos que llamar aquí el reject, ¿vale?
Lo podríamos llamar aquí como un parámetro más.
Y en el reject sería donde le pasaríamos, ¿vale?
Imagínate aquí que tenemos un error.
No sé por qué tendríamos un error, ¿eh?
Pero imagínate que hacemos aquí un try-catch.
No es la forma más, ¿vale?
Pero catch, un error.
Pues haríamos reject y le pasaríamos el error.
Esto no va a fallar de ninguna manera, pero imagínate que haces una llamada asíncrona, lo que sea.
Pues así lo podríamos hacer.
En este caso no sería necesario, pero solo para que lo sepas.
Así que así, solo y simplemente con esto, ya tendríamos que el obtener datos promise habría pasado a ser una promesa.
Y por lo tanto, ahora no deberíamos hacer esto, sino que podríamos hacer esto.
Aquí ya tendríamos la info y haríamos un console.log de la info.
Con este cambio, si lo ejecutamos, ¿vale?
Cuando pasen dos segundos, ¿vale?
Datos importantes, ya lo tendríamos.
Estaría haciendo exactamente lo mismo, pero en lugar de utilizar callbacks, estamos utilizando promesas.
¿Por qué es importante esto?
Es súper importante porque lo que estamos consiguiendo es que la gente vea que hemos entendido, que entendemos cómo podemos pasar de callbacks a promesas.
Si no entendéis los callbacks, las promesas, esto os está costando, practicad, ¿vale?
Porque esto la verdad es que es algo bastante básico y si no, muchas veces, o sea, realmente os queda mucho por delante.
Si no sabéis o no entendéis promesas, callbacks y temas de asincronía y si no entendéis cómo envolver esto y podéis resolver, os falta un montón y lo único que tenéis que estar haciendo es simplemente practicar.
Practicar con promesas y podéis hacer este tipo de cosas, ¿vale?
Si utilizo un callback, si utilizo una promesa e intentar de una a otra, ¿vale?
O sea, pasar una cosa que sea con un callback a una promesa y ver cómo funcionaría.
De hecho, os invito a que este ejercicio lo intentéis hacer y ya está.
Y el async await.
En este caso no necesitamos el async await porque no estamos devolviendo, o sea, estamos devolviendo directamente la promesa.
Podríamos hacer aquí esto, al ser una promesa, podríamos hacer aquí un await, obtener datos promise y podríamos hacer exactamente esto, ¿vale?
Pero dentro de la función no es necesario.
Podríamos hacer aquí esto.
Y esto, el de arriba, esto sería con promise.den, ¿vale?
Que es el que estamos haciendo.
Y este lo estaríamos haciendo con el await.
Pero estas dos cosas que estáis viendo, pues serían como dos formas diferentes de hacer lo mismo.
Una vez que el obtener datos promise devuelve una promesa, podéis concatenarla con el punto dem para que se resuelva.
O podéis utilizar el await para directamente esperar aquí, recuperar la información.
Bueno, aquí he puesto info, que es así, ¿vale?
Y hacer un console log.
Los dos funcionarían exactamente igual.
Estarían devolviendo después de dos segundos.
Lo importante es que sepáis que si hubiese un error, aquí tendríais que hacer el catch, ¿vale?
Console error del error.
Y aquí tendríais que hacer un try catch, ¿vale?
Donde estáis envolviendo lo que podría fallar.
Y esto ahora quedaría exactamente igual.
Y esta sería un poquito la diferencia.
¿En qué casos tiene sentido usar promesas en casi todas?
Porque obviamente las promesas son mucho, pero mucho, mucho, mucho mejores.
Y hay un ejercicio que lo explicamos.
A mí me gusta más con el den.
Bueno, muchas veces al final es una cosa de gustos, ¿vale?
Con este sería el segundo ejercicio.
Que entiendo que esto es lo que esperan.
Transforma la siguiente función para que funcione con promesas en lugar de callbacks.
Creo que hay aquí un...
Vamos a poner promesas, promises.test.js, ¿vale?
Y aquí obtener datos promise.
Es este de aquí.
Vamos a poner...
Me voy a traer los ejercicios de cada uno.
Y así, cuando los hagáis vosotros, además, vais a tener las soluciones.
Pero también vais a tener la posibilidad de hacer cada uno de forma separada.
Y yo creo que podría estar muy bien, por si hay alguno que os cuesta y tal, pues que lo tengáis.
¿Vale?
Entonces, en el index, aquí tenía obtener datos promise.
Este es el que nos tenía que pasar.
¿Vale?
Obtener datos promise.
Hacemos note test promises.test.js.
Y, claro, tarda dos segundos.
¿Vale?
Y ahora aparece dos veces el datos importante porque por aquí también lo tenemos.
O porque lo he puesto...
Ah, porque, claro, estamos ejecutándolo aquí.
¿Vale?
Esto lo quitamos.
Y ya tenemos el segundo ejercicio.
Lo tenemos ya.
Check.
Número tres.
A ver qué nos piden aquí.
Explica qué hace la función.
Identifica y corrige los errores en el siguiente código.
Si ves algo innecesario, elimínalo.
Luego, mejoralo para que siga funcionando con callback.
Y luego, haz lo que consideres para mejorar su legibilidad.
Pues, entonces, yo aquí esto lo dividiría como en diferentes partes.
¿Vale?
Vamos a poner esto por aquí, esto por acá.
Luego, haz lo que consideres.
Vale.
Entonces, primero, explica lo que hace la función.
Pues, vamos a explicarlo.
Se llama procesar archivo.
Lo que hace es leer un archivo que se llama input.txt, que justamente lo tenemos aquí.
¿Ves?
Que pone go, go, go.
Lo lee con la codificación UETF8.
Y aquí tenemos un callback.
¿Vale?
Fíjate que si no sabes qué son los callbacks, no te preocupes, que hoy lo vas a aprender.
¿Por qué?
Porque lo que hacemos con un callback es directamente aquí, es cuando se lea este archivo, entonces ejecuto esta función donde voy a tener el error o el contenido.
Si tengo un error, voy a avisar de que leyendo este archivo hay un error.
De hecho, yo creo que esto está mal, este es return false, pero bueno, sí, está mal porque le falta...
Dice, explica qué hace la función y corrige los errores.
¿Ves?
Es que es exactamente lo mismo.
O sea, están aquí como que te asegures que funcionan los callbacks.
Entonces, ahora arreglamos otra vez esto.
Error leyendo el archivo, return false, esto está mal.
Set timeout, ¿vale?
Otra vez un timeout.
Aquí tenemos texto procesado, contenido to uppercase, write file.
Entonces, lo que hace es, después de que pase un segundo, porque esto está en milisegundos, va a procesar el texto que ha leído previamente y lo va a convertir en mayúsculas.
Y una vez que lo ha convertido en mayúsculas, escribe un fichero que se llama output.txt, que todavía no lo tenemos porque no lo hemos generado,
que guarda el contenido de este fichero que hemos procesado, que básicamente lo va a poner todo en mayúsculas.
Y entonces, una vez que escriba este archivo, tenemos otro callback y ejecuta esta función cuando escribe el archivo.
Si hay un error, notifica que ha habido un error guardando el archivo, devuelve false, que esto, ya os digo yo, que está mal, ¿vale?
Esto está mal porque este return false está dentro del ámbito de esta función.
Por lo tanto, desde fuera, cuando ejecutemos esta función, no vamos a ser capaces de llegar a este return false, ¿vale?
Este return solo aplica a esta función que tenemos aquí, ¿vale?
Si no hay un error, dice archivo procesado y guardado con éxito y return true.
Bueno, pues exactamente lo mismo, ¿vale?
Identifique y corrige los errores en el siguiente código.
Los errores que yo veo serían muy parecidos a los que hemos visto antes y uno más.
Sería la falta de callback.
Aquí tenemos que pasarle el callback, ¿no?
Callback para que funcione con el callback.
Y aquí, de hecho me voy a copiar todo esto para que lo tengamos,
pero está bien porque es como un repaso del anterior.
Aquí el error que yo lo veo es que aquí debería tener un callback
y aquí en lugar de un return false, esto es que debería haber un error, ¿vale?
Pues entonces le pasamos callback, error.
Y aquí lo mismo.
Aquí en lugar de return false, aquí tendríamos que tener el callback y pasarle el error.
Y aquí como ha ido bien, pues tendríamos que poner callback y pasarle null, ¿vale?
Null porque no hay ningún error.
Esto sería el primer error que le encuentro.
Segundo error que yo le veo.
El setTimeout este que tenemos aquí es innecesario.
Realmente no sé por qué lo hace.
De hecho yo en la entrevista le preguntaría, oye, ¿por qué haces esto?
No, porque está haciendo un setTimeout para esperar un segundo,
pero esto no tiene mucho sentido.
Entonces yo le diría, esto no tiene sentido porque estás esperando un segundo para hacer algo
y esto es bastante problemático.
Por lo tanto yo esto se lo quitaría y directamente le pondría por aquí, ¿vale?
Y haríamos algo así.
Texto procesado, porque es que no tiene sentido.
A mí me parece que tiene más sentido hacer algo así.
No tiene sentido esperar un segundo para hacer mayúsculas el texto.
Ahora estaríamos leyendo esto, readfile, texto procesado, los callbacks estarían funcionando.
Al menos lo tendríamos así, ¿vale?
¿Qué más dice por aquí?
Si ves algo necesario, elimínalo.
Yo entiendo que esto es el setTimeout, ¿vale?
Esto es el setTimeout porque no tiene sentido esperar, ¿vale?
Ahí lo tendríamos.
Luego mejoralo para que siga funcionando con callback,
que yo creo que ya lo hemos hecho.
Esto debería funcionar con callback.
De hecho, vamos a probar.
Procesar archivo.
Y aquí tendríamos el callback, que aquí puedes hacer lo que tú quieras.
Esto ya funciona, ¿vale?
Y aquí ahora vamos a poner node y vamos a ejecutar el test.
Creo que tendríamos un test por aquí.
Vamos en index.
Vamos a procesar archivo, procesar archivo, ¿vale?
Vamos a procesar, procesar, test.js.
No sé si poner, ¿sabes?
El número del ejercicio.
Creo que os va a servir más así, ¿no?
Poniendo el número del ejercicio.
Y así lo vais a tener más fácil, ¿vale?
Entonces, importamos el procesar archivo, from, punto barra, solutions, index.
Y ya nos copiamos todo lo demás.
No todo es necesario, pero bueno, así no tardamos.
Y me voy a copiar solo esto de procesar archivo.
Procesar.
Ah, veo que hay dos.
Vale, pues esto.
Procesar archivo y ya lo tenemos.
¿Vale?
Esto debería funcionar.
Vamos a ver si realmente funciona.
Vamos a test, 3.test.js.
Y vemos que no funciona porque no lo he encontrado.
Ah, porque es que me he equivocado aquí poniendo el nombre.
¿Vale?
Test.js, test.js.
¿Vale?
Muy bien.
Y...
Vale.
Y aquí el import.
Hay un import aquí que no está funcionando.
Obtener.
Ah, no.
Este no es.
Este no es.
En el 3.
Vale.
Le falta la extensión.
¿Vale?
Y con esto ahora sí que debería estar bien.
Vamos a ejecutarlo.
Y el fs nos define.
No pasa nada.
¿Fs qué es?
Claro, nos falta, si os fijáis aquí, este fs es un módulo de Node.js que está utilizando
aquí, pero todavía no lo hemos importado.
De hecho, aquí tampoco, claro, a lo mejor es parte del problema, ¿no?
Que también tienes que saber que falta el fs y que tienes que importar el módulo.
Puede ser.
Import fs from node, dos puntos, fs.
Fs significa file system, porque esto lo que te permite es leer, escribir en el sistema
de archivos, ¿vale?
Así que con esto ya tenemos el ejercicio 3.
Vamos a ver ahora si todo funciona.
Funciona correctamente, pero también nos dice, luego mejoralo para que siga funcionando
con callback y dice, y luego haz lo que consideres para mejorar su legibilidad.
Esto está muy chulo porque esto nos abre la oportunidad de pasar esto a async await.
Y con el async await, luego haz lo que consideres para mejorar su legibilidad.
El async await nos va a hacer que mejoremos la legibilidad.
Esto aquí cada uno podemos hacer lo que queramos, ¿eh?
A lo mejor decir, no, no se puede mejorar la legibilidad.
Una cosa que podéis intentar para mejorar la legibilidad, aunque yo no sería muy fan,
¿vale?
No sería muy fan, podríais crear que los callbacks fuesen funciones.
Y esto estaría bastante bien que lo podáis entender.
O sea, esto está muy chulo porque así le demostráis que sabéis pasar funciones como parámetro.
Por ejemplo, este writeFile que hay aquí, ¿veis que aquí tiene una función?
Esta función para evitar el callback hell, el callback hell, para el que no sepa lo que es,
es lo que ocurre con los callbacks, que empieza a haber una anidación en la que aparece el río
y hace una doken, pero ¿ves esto que ocurre aquí de ta ta ta, callback, ta ta ta, ¿no?
Y empieza a ver esto, que es como una pirámide de izquierda a derecha, y esto se le llama callback hell.
Aquí, si os fijáis, ya poco a poco va ocurriendo.
De hecho, en el original pasaba todavía más.
¿Veis que hay aquí como una pirámide que esto iría cada vez a peor?
Seguramente en la entrevista estarían pensando que lo comentes, ¿no?
Que digas, oye, esto es que puede existir un callback hell y tal.
Una forma de solucionar el callback hell, que no suele utilizar mucho, pero la verdad es que está bastante bien,
es el hecho de evitar que las funciones las tengas siempre en línea.
Aquí hay bastantes opiniones, por ejemplo, estoy seguro que si estaba Gonzi,
porque Gonzi os dirá, a mí no me gusta esto porque esto lo que hace es separar el código de donde se utiliza.
Pero hay otra gente que os dirá, tiene sentido separarlo en funciones porque así se aplana el código.
Pero os voy a enseñar cómo lo haría lo de aplanar el código con esto y luego vosotros decidís.
En el write file este, lo que podéis hacer aquí directamente sería hacer un handle write, ¿vale?
Y esto pasarlo a una función, ¿veis?
Ahora lo tenemos ahí en una función, teníamos esto en una función y este handle write lo podríamos cambiar.
Podríamos hacer esto y lo cambiamos aquí, handle write, pim, pam.
Y lo mismo podría ser con este callback de aquí.
Este callback de aquí que tenemos aquí, pam, lo podríamos llamar handle read file y ya está.
Cons handle read file.
Y esto lo pasaríamos a una función.
¿Qué es lo que hemos conseguido con esto?
Bueno, lo que hemos conseguido es aplanar, si os fijáis, ahora el anidamiento no existe, es solo un nivel.
Fijaos que antes tendríamos como una, ¿ves?
Teníamos como una pirámide y ahora lo que tenemos es que está en el mismo nivel,
tanto el handle read, el write, no sé qué.
Lo malo, a ver, esto a veces tiene sentido en funciones que sean muy sencillas y os puede simplificar bastante el código.
Lo malo es que tienes que tirar como más del hilo, ¿no?
Tienes que ir al handle read file, ir aquí y aquí entonces ver que el write file llama el handle write y ir aquí.
Yo esto son cosas que comentaría mientras las estoy haciendo, ¿vale?
¿Por qué?
Porque aquí dice, mejora para que siga funcionando con callbacks.
Entonces yo le diría, mira, yo intentaría hacer esto para si por lo que sea no pudiese crear promesas, pues haría esto porque creo que esto puede mejorar el código.
Incluso esto lo podría sacar fuera del scope de la función y ponerlo aquí para ver si en otro sitio tiene sentido utilizarlo, ¿no?
O sea, podrías explicar un poco.
Eso por si quieres ahí tener la explicación completa.
Pero yo creo que lo clave es cuando dice, luego haz lo que consideres para mejorar su legibilidad.
Lo que está clarísimo es que cuando aquí dice que mejor es su legibilidad es dejar de utilizar callbacks y pasarlo a sinkawait o a promesas.
Yo diría más a sinkawait.
¿Cómo podemos pasar esto a sinkawait?
Mira, lo voy a hacer en otro ejercicio.
O sea, voy a dejar este para que lo tengas aquí de referencia.
Pero justo aquí debajo vamos a hacer procesar archivo promise, ¿vale?
Puedes llamarle promise, le voy a llamar promise porque en realidad cuando utilizáis a sinkawait en realidad estamos hablando de promesas, ¿vale?
Yo quitaría los callbacks y lo que haríamos directamente es aquí, en este readfile que tenemos aquí, ¿vale?
Aquí directamente podemos hacer el await, pasamos la función a asíncrona y aquí en lugar de utilizar fs.readfile utilizaríamos fs.promises.readfile, ¿vale?
Entonces quitamos esto, aquí ya estaríamos leyendo el archivo y ahora directamente haríamos el texto procesado justo después.
Y luego lo escribiríamos, ¿vale?
Esto es lo que haríamos.
Esto lo comentaríamos por ahora, pero ahora os comento más cosas de esto.
Fijaos todo esto, ¡pum!
¿Vale?
Y aquí tendríamos que hacer o el await o hacer un return.
Y aquí también fs.promises.readfile, ¿vale?
Y este handlewrite lo quitaríamos.
Y esto es lo que tendríamos.
Ahora, ahora, ¿por qué uno?
¿Por qué no necesitamos hacer el return new promise?
¿Por qué esto funciona y tal?
¿Qué es lo que pasa?
La Node.js, antiguamente, toda su API, todas las bibliotecas que tenía Node.js funcionaban con callbacks, ¿vale?
Que es el sistema que hemos visto antiguo, que lo tenemos aquí, ¿vale?
Entonces, este readfile que tenéis aquí, o este writefile, el readfile, ¿veis que aquí acepta un callback?
Esto es como funcionaba antes.
Por suerte, aunque Node.js funcionaba antes así, ahora tiene una API que funciona todo a compromesas, ¿vale?
Entonces, en lugar de tener que hacer esto, y esto lo voy a dejar aquí aparte, ¿vale?
En lugar de tener que hacer esto, que esto sería el old way, ahora hay un new way.
And this is the way, ¿vale?
And this is the way.
Y el new way es utilizando fs.promises.readfile.input.
Es exactamente la misma API, solo que aquí no necesitas utilizar aquí el callback, ¿vale?
Aquí no va el callback, sino que esto devuelve una promesa.
Y aquí ya puedes hacer lo que tú quieras, ¿vale?
Esto es lo que pasa después.
Y aquí tendríamos el otro caso.
Console.log.
Esto es lo que pasa después, ¿vale?
O sea que esta sería la forma antigua, ¿vale?
Older.
Y esta sería la nueva, ¿vale?
Pero fíjate en la diferencia.
fs.readfile o fs.promises.readfile.
Lo bueno del new way es que también podéis hacer así.
Promises.readfile.input.txt.wtf8, ¿vale?
Porque cuando una promesa la podéis resolver con el .den o podéis esperar que se resuelva con el await, ¿vale?
Y entonces podéis hacer cualquiera de las dos.
O con await, ¿vale?
Así que así lo tendría, ¿eh?
Serían de las dos formas.
Luego, si tenéis clarísimo que el único que vais a utilizar del file system son las promesas,
esto funciona cuando hacéis así.
Import fs from node fs, ¿vale?
Pero, ¿qué pasa?
Imaginad que esto a tomar por saco.
Esto sabéis que no lo vais a usar nunca.
Pues lo que podéis hacer para simplificar, en lugar de tener que poner fs.promises, podéis traeros fs.promises
y directamente este file system ya funcionará perfectamente con promesas sin necesidad de tener que poner el .promises, ¿vale?
Así que si queréis que todo el file system que queráis que sea asíncrono funcione con promesas, lo podéis hacer así.
Y de hecho esto, pues se lo podéis comentar también.
Le podéis decir, oye, pues esto, el fs.promises, voy a cambiar esto, voy a poner barra promises y entonces estos fs que tenía por aquí.
O incluso podéis tener dos, podéis decir, import fsp from node fs.promises.
Y entonces tendríamos el fs que funciona con el de antes y el fsp lo vamos a utilizar aquí, ¿vale?
Aquí, para no tener que poner esto y ya lo tendríamos.
Pero esperad que todavía queda un poquito, ¿eh?
Queda un poquito.
¿Por qué?
Porque lo que tenemos aquí en este tema de asincronía, cuando se usa wait siempre se usa el try-catch, ¿no?
Claro, eso es lo que íbamos a comentar, ¿no?
El problema es que hemos perdido de alguna forma que este error que comentamos aquí, ¿vale?
¿Qué pasa si esto da un error?
Pues no lo estamos controlando.
Entonces lo que deberíamos hacer es, en cada uno, este, poner aquí un try-catch, ¿vale?
Y estos errores que habíamos puesto aquí, pues tendríamos que ponerlo aquí.
Y aquí tendríamos que hacer un throw del error, ¿vale?
Este callback error se traduciría a este throw del error.
Y aquí, pues pasaría exactamente lo mismo.
Tendríamos que poner esto aquí.
¿Por qué?
Porque si no esta información de si ha habido un error, que no sé qué, la estaríamos perdiendo.
Tenemos que hacer un catch del error, ¿vale?
Y aquí un throw del error.
Y con esto ahora sí lo tendríamos exactamente igual, ¿vale?
Ahora sí que tendríamos que funcione exactamente igual.
Yo creo que sí que se entiende mejor.
El try-catch, podríais hablar con la persona que usted está haciendo la entrevista y decirle,
bueno, también podría, como no me importa, podría envolverlo todo, no sé qué.
Bueno, he puesto los errores al revés, perdón, he puesto los errores al revés, pero ya lo habéis entendido, ¿no?
Vale, pues ahora sí que lo tendríamos igual.
Y esto sería con promesas.
Tendríamos aquí el texto procesado, texto procesado, con selerror, no sé qué, y ya lo tendríamos aquí.
Y ya está.
Así que con esto tendríamos el procesar archivo promis y esto debería funcionar así, haciendo una wait y ya funcionaría.
Me pica el cerebro que el readfile no tenga asignación.
Bueno, es que no tiene por qué tener...
Ay, perdón, es que sí o yo.
Le iba a decir, no hace falta tener asignación.
No, esto soy yo que no lo he hecho.
Esto tiene que ser contenido aquí vacío, el contenido tiene que estar aquí y el contenido tuvo uppercase.
Esto es que se me había olvidado, ¿eh?
Le he puesto una e, pero esto debería ser error, error, aquí también error y error, ¿vale?
Y con esto ahora sí que lo deberíamos tener.
Claro, tenemos que guardarle una variable, que si no, no tenemos que tener.
A tener en cuenta que siempre puedes combinar async await con denicatch.
Eso tienes toda la razón.
Por ejemplo, esto aquí, si queréis, por lo que sea, podéis, en lugar de hacer esto, podéis hacer esto, que a veces queda bastante chulo.
Hacéis esto y podéis concatenar aquí el catch directamente, que a mí es una cosa que me gusta bastante, que mucha gente no entiende y no conoce, ¿no?
Y es que al final lasync await son premisas, lo que significa que podéis concatenarle el catch, pero podéis seguir haciendo una wait.
Y así, si hay un error, entraría aquí sin necesidad de utilizar lo que sería todo el error que teníais antes.
Y aquí está chulo sobre todo si lo que queréis es, ¿vale?
Hacéis un error, pero queréis que siga funcionando correctamente.
Entonces, si hay un error y entra aquí, en el contenido se le va a asignar esta cadena de texto vacía, ¿vale?
Lo cual puede estar interesante para decir, oye, en la consola se ve que ha habido un error, pero no voy a evitar que se siga ejecutando el código.
Y así le hago un return del error.
Así que, bueno, os dejo este comentario y este código para que tengáis las dos cosas, que está bastante bien.
Vamos a ver si esto funciona.
Este ejercicio era el 3.
Ah, bueno, pero veo que teníamos aquí procesar archivo y procesar archivo promise, ¿vale?
Vamos a ver si este procesar archivo, mira, tenía aquí el test, ¿vale?
Procesar archivo, lo tenemos por aquí, esto para acá, procesar archivo promise.
Vamos a ver si funcionan procesar archivo promise.
Vamos a ver si pasa los test, igual, vale, sí que pasa los dos test, pues está funcionando correctamente, ¿vale?
Así que el 3, tanto, este era más complicado.
Leí que estaba mal mezclar den y catch con away, pero sí queda mejor.
No sé dónde habéis leído eso, pero no tiene mucho, o sea, no está mal.
Lo que puede ser es que lo hagas mal, pero no está mal.
O sea, a mí me parece que puede tener sentido.
De hecho, lo he visto bastante, ¿no?
Este está muy chulo.
Este lo preguntan mucho, ¿vale?
Este lo preguntan mucho y además creo que tiene trampa.
¿Cómo mejorarías el siguiente código y por qué?
Arregla los test si es necesario.
Mira, os voy a explicar este.
Este es muy fácil, pero también tienes que entender por qué se hace, ¿vale?
O sea, no solo es arreglarlo, sino que es entender el por qué.
Y os voy a enseñar una forma bastante chula para que veáis el por qué y va a estar muy bien, ¿vale?
Mira, tenemos este código que si os fijáis, este código es síncrono porque pone read sync.
Mira, os lo voy a explicar hasta con el archivo 1, el archivo 2 y el archivo 3.
1, 2 y 3, ¿vale?
Y entonces, imaginad que tenemos otro código aquí.
Otro código, este otro código por aquí, ¿vale?
Que esto sería otro código, ¿vale?
Esto es tal y como está ahora representado el código que tenemos aquí, ¿vale?
¿Por qué?
Porque hace el read file sync, este y este, ¿no?
Entonces, hace esto, bloquea todo, esto, esto y luego otro código que tengamos por ahí, no hace falta que sea el mismo archivo, sino otro código, pues se ejecuta justo después.
¿Por qué?
Porque fijaos que está bloqueando, ¿vale?
Está bloqueando el hilo principal.
JavaScript es mono hilo.
Y lo que está pasando aquí es que hasta que no termina de leer este archivo, no ejecuta otro código.
No está ejecutando absolutamente nada, ¿vale?
Y entonces, cuando termina, llega esto y luego esto.
Y entonces está bloqueándolo todo, ¿vale?
Esto sería el caso del código del ejercicio.
Este sería el caso 1.
Código del ejercicio, ¿vale?
Muy bien.
Entonces, ¿qué es lo primero que mucha gente haría aquí para arreglarlo?
Y puede tener sentido, ¿vale?
No podría, no estaría mal.
Lo primero, mira, vamos a traernos esto en el index.
Vamos a poner aquí ejercicio 4.
Ejercicio 4, ¿vale?
Este fs no lo necesitamos porque ya lo tenemos por ahí.
Y esto ya lo tenemos.
Para que lo entendáis y lo veáis muy claro de por qué esto es importante,
vamos a poner aquí un console time leer archivos.
Y vamos a poner aquí al final un console time end leer archivos.
Igual no sabíais que el console también tiene un time y un time end.
Y esto está muy chulo porque lo que te permite es detectar el tiempo que pasa desde este punto, ¿vale?
Hasta este punto, ¿vale?
Entonces, lo que estamos viendo aquí es decir, ¿vale?
¿Cuánto tiempo tarda?
De la línea 90 a la 95 en ejecutarse.
Así que si ahora ejecutamos aquí el node solutions index.js, ¿vale?
Y veo que...
Ah, es que yo creo que esto está mal porque esto debe ser file sync, de hecho, ¿no?
Read file sync, no sé.
Esto está mal.
Yo creo que es así, la API.
¿Ves?
Vale.
Podemos ver que ha tardado 400 milisegundos, ¿vale?
400 milisegundos ha tardado en leer los tres archivos porque, bueno, 400 milisegundos no, 0,600 milisegundos.
Es muy poco, ¿eh?
Es muy poco.
Pero el problema muchas veces es que esto, si llegado el caso, puede tener un impacto mayor si se lee muchas veces y tal.
Lo primero que habría que hacer, obviamente, sería pensar en pasar esto en una función asíncrona.
Y como hemos visto antes, pues podemos utilizar el fsp, ¿vale?
Que sería el de las promesas.
Y en lugar de utilizar read file, quitamos el sync y aquí lo que hacemos es esperar todas las promesas.
Así que hacemos un await.
Y ahora os explico qué caso es este.
Ejecutamos, ¿vale?
Y más o menos podemos ver que tarda lo mismo.
O sea, funcionar funciona.
Tarda más o menos lo mismo.
Igual un pelín menos, no sé.
Yo creo que tarda más o menos lo mismo.
Porque, total, lo que está pasando aquí es algo muy parecido, pero este sería el caso 2, ¿no?
El caso 2, que sería con el async, que aunque nosotros no lo veamos que vaya más rápido, vamos a ver por qué no lo vemos que va más rápido, pero por qué es mejor.
Y este sería usando async.
Lo que está pasando aquí es parecido, ¿vale?
Pero en lugar de bloquear todo esto, lo que está pasando aquí es que aquí estamos utilizando read file async 1, ¿vale?
Esto aquí.
El read file async, vamos a tener esto otra vez aquí, ¿vale?
Es un poco parecido, pero ya veis que es un poco también diferente.
¿Por qué?
Porque lo que estamos haciendo es no bloquear todo el tiempo.
Lo que estamos haciendo es que hasta que esto no esté aquí, estaría leyendo,
pero el otro código que tenemos aquí se va a poder ir ejecutando en estos huecos que hay aquí.
Lo que va a permitir es que, aunque el tiempo de leer los archivos es el mismo,
lo que podemos ver es que está haciendo más cosas.
Lo que está ocurriendo es que en estos huequecitos está haciendo cosas que nosotros no vemos.
Obviamente, leer el fichero tarda lo mismo, pero mientras está leyendo el fichero,
no está bloqueando el procesamiento, ¿vale?
El hilo de JavaScript no está bloqueado y, por lo tanto, está ejecutando otro código en estos huequecitos.
Que esto incluso, a lo mejor, lo he hipersimplificado, ¿eh?
Pero puede ser que sea más bien así, ¿no?
Que tenga más huequecitos por ahí, que lo deje, tal, tal.
Pero esta ha sido un poco la idea, ¿no?
Al haberlo hecho asíncrono, lo que estamos haciendo es, vale,
mientras necesito el procesamiento de leer el fichero y tal,
pero mientras se lee el fichero, esto lo está poniendo como en un stream de datos
y lo que está pasando muchas veces es que eso no se bloquea,
sino que puede conseguir hacer otras cosas mientras.
Entonces, ¿qué pasa?
Que el tiempo, el tiempo, fíjate, en síncrono y en asíncrono,
el tiempo de leer los ficheros es el mismo.
No hemos visto una mejora de tiempo,
pero lo que sí que pasa es que se libera mientras está leyendo los ficheros.
De forma que si tuviéramos otro código, se tenga que ejecutar y tal,
veríamos que sí que se ejecuta.
Y eso es lo interesante, el no bloquear,
que mientras no esté haciendo nada, que esté bloqueado, ¿vale?
Entonces, el tema es que al menos ha mejorado,
pero todavía lo podemos mejorar más y ya me imagino que estás en el chat ahí
echando espuma por la boca, pero hace esto, no sé qué.
A ver, otra forma en la que podéis hacer esto,
y esto es bastante importante y tenéis que explicarle de por qué lo podéis hacer,
es el hecho de hacerlo en paralelo, ¿no?
Esto ahora lo que está ocurriendo es que se está haciendo de forma síncrona,
pero de forma secuencial.
¿Qué quiere decir esto?
Pues que sigue haciendo que lee el primer fichero
y aunque cuando no necesita procesamiento, hace otras cosas,
hasta que no termina de leer el primer fichero,
no empieza a leer el segundo.
Esto significa que aunque lo haga de forma síncrona,
lo está haciendo secuencial, porque está haciendo uno detrás del otro.
Por lo tanto, necesitamos un tercer caso, que todavía sea mejor,
que sea utilizando async en paralelo.
¿En paralelo por qué?
Porque la lectura de los ficheros no dependen entre ellos mismos.
O sea, que tú leas este fichero, este fichero y este fichero,
no dependen entre ellos.
Otra cosa sería que al leer el archivo 1,
esta información la necesites para leer el archivo 2.
Esto sí que será una putada, porque entonces necesitas esperarlo.
Pero como no dependen unos de otros,
lo que puedes hacer es hacer las tres lecturas en paralelo.
O sea, en lugar de hacer 1, 2, 3,
lo que puedes hacer es decir, vale, pues el 1, el 2 y el 3.
Y esto además, pues va a pasar un poquito lo mismo.
Solo que simplemente, fíjate que ahora vamos a hacer esto.
Esto seguramente va a ser un poquito más, todavía mucho más, pues así, ¿no?
Que va a tener rojo, verde, rojo, verde y tal.
Pero lo que vamos a hacer al hacer esto en paralelo totalmente,
fíjate que aquí sí que vamos a ahorrar tiempo.
¿Cómo lo hacemos? Pues nada.
Promisor, y esto lo que pasamos es un array
donde tenemos que tener todas las promesas que queremos que se resuelvan.
Aquí tendríamos 1, 2 y 3.
Le cambiamos a archivo 1, archivo 2, archivo 3.
Quitamos todo esto.
Lo voy a comentar, ¿vale? Para que tengáis el código.
Y aquí ya tendríamos el fichero, el 1, el 2 y el 3, ¿vale?
Para ponerle algún nombre.
El 1, el 2 y el 3, pues ya los ponemos aquí.
1, bueno, mira, ya tenía nombre.
O sea, que lo vamos a poner con el mismo nombre.
2 y 3, ¿vale?
Y esto ya no lo necesitaríamos.
Estaríamos haciendo lo mismo, pero lo que estamos diciendo es,
oye, quiero que me resuelvas todas las promesas que le pasamos en este array
y lo que quiero es que las hagas las 3 de golpe.
Conforme las vas haciendo y una vez que termines todas,
entonces me das aquí otra vez el control y aquí tengo toda la información.
Fíjate que es importante, por ejemplo, si pasas el archivo 3, el primero,
tened en cuenta que el archivo 3 ahora será el primero, ¿vale?
Entonces, la posición del array cuando lo desestructuramos,
tened en cuenta que cambia.
Luego, un tema importante.
Aquí, como esto es una promesa, esto devuelve una promesa,
tenemos que esperar, hacer un await aquí de la promesa.
Y también lo mismo, podríamos hacer un den.
Si queréis, podríamos hacer un den y hacerlo de otra forma.
Pero vamos a hacerlo con el await, ¿vale?
Que queda más limpio.
Esperamos que se resuelvan todas estas promesas
y aquí vamos a tener, según el orden de cada una de las promesas,
por ejemplo, ahora leemos primero el archivo 3.
Bueno, pues aquí tenemos el archivo 3, aquí el archivo 1,
pues aquí el archivo 1.
Conforme vais cambiando y vais moviendo,
tened en cuenta que entonces también cambian aquí, ¿vale?
Que está relacionado, que esto es una cosa de mucha gente
que se cree que esto es magia, no es magia.
Y tendríamos esto.
Archivo 1, archivo 2, archivo 3, ya lo tendríamos así, ¿vale?
Y ahora, cuando ejecutemos esto, ¿vale?
Pues fíjate que ahora sí que vemos una mejora sustancial en el tiempo.
Si antes estábamos viendo que estaba entre 0,5, 0,6,
ahora sí que vemos que hay veces que es 0,2, 0,3, ¿vale?
Se ve que impacta positivamente en el tiempo que tarda.
Y es porque estamos consiguiendo esto de aquí.
A lo mejor aquí me he pasado, ¿vale?
Ha sido un poco exagerado.
Pero ya podéis ver que sí que hay una mejora de los tiempos, ¿vale?
Porque al hacer las llamadas, las estamos haciendo las tres en paralelo,
pues ya lo tendríamos.
Luego habría un caso 4 todavía, ¿vale?
Un caso 4, no para que vaya más rápido,
pero sí para controlar un poquito mejor la ejecución.
Que sería utilizando, usando async en paralelo,
pero con all set.
No es que cambie exactamente el tiempo,
pero sí que puede cambiar el cómo se comporta el promisor.
El problema que tenemos con el promisor
es que si una de las promesas falla,
el problema es que va a fallar todo.
Entonces, tendríamos que tener aquí un cache, por ejemplo,
y con que una falle, y lo vamos a ver ahora,
console error.
Imagínate que aquí tenemos, por ejemplo, el archivo 2,
me invento 1.
Ahora, si intento ejecutar esto, ¿vale?
Fíjate que me falla.
Y me dice justamente, oye, que ha habido aquí un error,
porque el console error este no funciona.
Y por lo tanto, claro, como falla esto,
también me está petando aquí porque me dice que no es iterable, ¿vale?
Esta wait me dice que no es iterable.
O sea, que aquí debería asegurarme, al menos,
de devolver un array vacío para que no me pete, ¿vale?
Pero fíjate, tenemos un error, ¿no?
No existe este archivo directorio intentando abrir esto
y dice, vale, pues, entonces, ¿qué pasa?
Que el archivo 3, archivo 2 y archivo 1,
si miráis este return de aquí,
vais a ver que no me está devolviendo la información
tal y como espero.
Lo que me va a pasar aquí es que me va a decir que está vacío, ¿ves?
Undefined, undefined, undefined.
Cuando lo que realmente espero, cuando va todo bien, fíjate,
es que, al menos, me dice, hola, ¿qué tal?
Porque está leyendo el archivo 1, que es hola,
el archivo 2, que es que, y el 3, que es que tal.
O sea, que es tal, ¿no?
Y mezclándolo todo debería ser hola, ¿qué tal?
Cuando uno peta, por ejemplo este,
el problema que está pasando es que, de repente,
es todo undefined, ¿vale?
Undefined, undefined, undefined.
Si en lugar de utilizar el all, podríamos utilizar el all settle.
El all settle lo que nos va a permitir
sería tener un control más granular
de si falla o no falla 1.
En lugar de poner aquí un catch,
podríamos mirar aquí en el archivo, ¿vale?
Vamos a poner, para que veamos lo que tiene,
archivo 3, ¿vale?
Archivo 3, vamos a ver qué es lo que tiene.
Fíjate que el archivo 3 ahora tiene
status, fulfill y el value, tal.
Lo que estamos viendo es que ahora vamos a poder controlar,
por ejemplo, el del archivo 2, que es el que peta,
nos va a decir, oye, el archivo 2, fíjate que se ha rechazado
y esta es la razón, pero no ha petado.
Y, por lo tanto, lo que podemos hacer ahora
es recuperar el valor de cada promesa en el caso de que esté
y ponerlo aquí.
Podríamos poner value, punto value y punto value, ¿vale?
Y esto lo que nos permite es que,
aunque una de las promesas pete,
al menos el resto las podemos reutilizar.
Se lo podríais comentar, porque me parece,
esto ya sé que me parece un poco más avanzado,
pero, ¿ves? Ahora es hola undefined tal.
¿Por qué? Porque una, la del medio,
ha petado, pero en lugar de decir,
oye, pues las otras no las muestro,
al menos lo que haces es un control
más granular. Así que si sabes
que una promesa puede ser que pete,
haces un promise all settle
y puedes acceder al value y así dices,
bueno, como el resto sí que ha funcionado,
pues que siga funcionando y esa que ha petado
por X motivo, pues lo que vamos a hacer
es que mostrarla de alguna forma.
De hecho, para que quede mejor,
incluso podríamos hacer algo así, ¿vale?
Podríamos decirle, vale,
pues vamos a tener aquí un return
que tenemos en archivo 3,
bueno, vamos a ponerlo en orden,
archivo 1, archivo 2, archivo 3,
con el value, ¿vale?
Vamos a tener cada uno de los value,
podríamos filtrar,
filter, bolean,
bueno, puedes hacer bolean
o puedes hacer que sea
todos los que sean undefined, por ejemplo.
Lo voy a poner con bolean,
aunque no sería correcto por si hay uno vacío,
pero bueno, si es vacío tampoco es muy importante,
qué mala.
Vamos a poner bolean.
Pero bueno, solo para que te hagas a la idea
de una cosa que podrías hacer, ¿no?
Y aquí separarlo así.
Y aquí ya, con esto,
podríamos ponerlo aquí,
que esto fuese el mensaje
y filtrando esto,
vamos a poner aquí message,
pues ya no aparecería, por ejemplo,
los que son undefined.
Message.
Y al menos, pues quedaría bastante interesante, ¿no?
Hola, tal.
No pone el que,
porque el que como ha sido undefined,
lo estamos filtrando aquí.
Si no, podríais poner aquí, ¿eh?
Type of, por ejemplo, value,
que type of value sea diferente a undefined, ¿vale?
Y ya, pues, sería mejor que no el bolean,
que es un poco pirata.
Sea diferente a undefined.
Bueno, espérate,
porque que sea undefined
o que sea diferente a undefined.
A ver, porque me ha dejado ahí un hueco.
Ah, porque puede, claro,
porque le he dejado en algún sitio,
porque este value,
type of value undefined,
value, value.
Espérate.
Debería ser diferente a undefined, ¿no?
Este value puede ser,
debería ser undefined.
Ay.
La madre que me parió,
que esto debería ser una cadena de texto.
Ya está, ya está.
Ya está.
Ahora sí.
Ya está flipando.
Ya está.
¿Veis?
Ahora queda bien.
Eso en el caso de que queréis filtrar
los valores que sean undefined y tal.
Esto ya me parece más avanzado, ¿vale?
Esto me parece que no lo haría yo
para un junior trainee.
Esto me parece un poquito más avanzado.
Si lo sabes, buenísimo.
Vas a quedar como un dios.
Pero no me parece que sea parte de la solución
que necesitéis comentar, ¿vale?
Solo para que lo tengáis claro y ya está.
No he probado el test.
Este es el ejercicio.
Vamos a poner ejercicio 4,
que yo entiendo.
No sé si hay un test de esto.
Ah, sí.
Leer archivos.
Leer archivos.
Et, et, et.
Parece que sí.
Hola, ¿qué tal?
Ese es el mensaje que debería aparecer.
Vale.
Entiendo que aquí me he petado esto.
Vamos a hacer esto.
Vale.
Y este describe 4.
Vamos a poner 4.test.js.
Lo bueno de esto, ya os digo que al final os invito a que hagáis vosotros también estos
ejercicios porque está bien que yo os lo explique, pero lo importante de verdad es mover las
manitas.
Es que si no lo practicáis, no lo vais a entender nunca.
Yo os lo puedo explicar y está genial que os escuchéis y que veáis cómo se hace y tal,
pero es que si al final no lo hacéis, no lo vais a terminar de entender y os equivoquéis.
Sabes que digas, hostia, me he equivocado aquí, no lo he hecho bien, lo que sea.
Este tipo de cosas al final es súper importante que os equivoquéis y que os pete porque ahí
es donde realmente está el crecimiento.
Ejercicio 5.
Ejercicio 5 parece bastante fácil y vuelve a ser un poco parecido al que hemos hecho
antes.
Yo creo que está muy pensada esta práctica para ver si realmente entiendes asincronía
en JavaScript, callbacks, promesas y todo esto.
Porque dice, escribe una función delay que retorne una promesa que se resuelve después
de n milisegundos.
Es que esto es exactamente lo mismo.
Yo entiendo que es como que están intentando ahí que te asegures, es exactamente lo mismo
esto, solo que un poquito más configurable.
Y aquí te da algunos ejemplos.
Es por async function delay y te dice, vale, si le pasas 3 mil milisegundos, después de
3 segundos haces el console log.
Este es muy típico y muy sencillo, ¿vale?
Básicamente, aquí primero devolvemos una promesa, ¿vale?
Tenemos el resolve.
Y aquí, pues nada, setTimeout.
Aquí le pasamos el callback y esto le pasamos el número, el time que viene del parámetro
time.
Y ya está.
Aquí, pues, se resuelve y ya está.
Se resuelve y lo que se resuelva, pues se hace y ya está.
A ver, lo que, a ver si necesitamos, vale.
Pues ya está.
Es simplemente esto.
Esta sería una función delay.
Una función que, pasado este tiempo, se resuelve y ya está.
De hecho, este resolve, fíjate que como no tiene nada y este timeout tampoco, podrías
hacer esto directamente y te quedaría todavía mejor, por si tiene ganas de hacerlo así.
Un fallo que a veces la gente hace es pensar que puedes utilizar aquí el promise resolve
y aquí, pues, no se puede utilizar, ¿vale?
Lo tenéis que hacer así.
Return new promise, cuando se resuelve, pues cuando el setTimeout le pasas el callback
del resolve y aquí el tiempo.
Y este sería, básicamente, el ejercicio número 5.
Número 5, vamos a poner...
Ah, el 5 no tiene test.
Bueno, pues nada.
El 5 se queda sin test, pero os invito a que lo hagáis, el test, que vais a aprender
bastante.
Bueno, ese era fácil.
En esos casos, ¿cómo se limpia el timeout cuando se devuelve una promesa?
Interesante.
Cosas que puedes hacer.
Claro, el tema es que cómo puedes realmente limpiar este timeout porque no lo vas a poder
limpiar.
Una cosa que vas a poder hacer, por ejemplo, sería dejar que se ejecute de una y ya está.
O envolverlo de una forma totalmente diferente que devuelva un objeto en el que puedas.
O sea, podrías devolver aquí, por ejemplo, un objeto que tengas la ID del timeout y por
otro lado la promesa, ¿sabes?
O sea, podríamos tener aquí, por ejemplo, timeout ID, ¿vale?
La promise y entonces tú haces aquí return.
Esto sería el new promise, resolve.
Aquí tendríamos el timeout ID.
Timeout ID, setTimeout, ¿vale?
Tendríamos el resolve y el time.
Y aquí lo que devuelves es, por un lado, el timeout ID o incluso podrías devolver un clear
interval, ¿vale?
Que esto lo que hace es clear timeout, timeout ID, clear timeout.
Todavía mejor.
Y por otro lado tendrías la promesa.
Entonces, lo que podrías llegar a hacer sería algo así.
Podrías tener un delay, await delay, o sea, podríamos delay.promise.
O sea, cuando haces el delay tendrías aquí la promesa y el clear timeout.
Aquí tendrías el delay de 500.000 segundos, ¿vale?
Promise.
Esto está chulo, ¿eh?
Está chulo porque no es una cosa que se suele ver.
Entonces, tú podrías hacer el await del promise aquí, ¿vale?
Haces la, espera la promesa.
No hace falta hacer esto, espera la promesa.
Pero cuando quieras podrías hacer un clear timeout y ya está.
Entonces, ten en cuenta que esto podría no resolverse nunca, claro.
Porque si limpias justamente, si haces un clear timeout justo cuando tienes esto,
pues a lo mejor nunca se resuelve y ya está.
Pero bueno, a veces tiene sentido que algo no se resuelva.
Porque al final este await tiene que venir con código aquí que se supone que depende de la promesa.
Pero podrías hacer algo así, algo parecido.
Ya está.
Los objetos son la vida en JavaScript.
Te puedes hacer una de locuras y esta podría ser una, ¿no?
Me explotó la cabeza.
Bueno, pero a ver, esto ya me parece bastante hardcore, ¿eh?
Esto no es para Juniors of the Trinity.
Esto no sería para Juniors of the Trinity.
Así que os lo voy a dejar como comentario, solo para que lo tengáis.
Pero no os preocupéis de esto, ¿eh?
Pero básicamente es devolver un objeto y solo utilizar la parte del objeto que te interese.
Ojo con este, que este está bastante chulo.
Voy a cerrar aquí unas cuantas cosas.
Esto también y esto también.
Este es un ejercicio muy completo, muy interesante,
que os recomiendo a todos y a todas que lo hagáis.
Hay muchas cosas que practicáis con esto.
Dice, vamos a crear nuestra propia utilidad .env en el archivo .env.js.
O sea, aquí, ¿vale?
Y dice, la utilidad debe devolver un método config que lee el archivo .env y añade las variables.
Bueno, si no sabéis lo que es el .env, para el que no sepa lo que es el .env,
esto es seguramente uno de los paquetes más utilizados del mundo a día de hoy en Node.
¿Ves?
Tiene 34 millones de descargas semanales.
O sea, 35 millones de descargas semanales.
Yo que sé, a ver cuánto se descarga React, para hacernos a la idea.
¿Cuánto se descarga React?
React se descarga 21 millones.
O sea, se descarga menos.
Se descarga menos.
Webpack.
Yo que sé, que Webpack también es bastante utilizado.
Webpack se descarga 25 millones.
O sea, .env se descarga más que React y que Webpack.
¿Vale?
Para que os hagáis una idea del impacto que tiene .env.
O sea, es increíble este paquete.
Este paquete lo que hace es que detecta cuando tienes un archivo .env,
que lo voy a poner por aquí, por ejemplo.
Vamos a poner .env.
Y aquí, pues, puedes poner dbhost, hola, bueno, localhost, por decir algo.
Y aquí, puerto 1, 2, 3, 4.
Y una vez que tú tienes este archivo aquí,
llamando estas dos líneas de código,
lo que hace es pegar el contenido de este archivo en el process.env, punto,
y el nombre de la variable de entorno.
Esto lo has tenido que utilizar, aunque sea sin querer,
lo has tenido que utilizar.
¿Por qué?
Porque es que es súper típico y se utiliza un montón en un montón de sitios.
Un montón de veces.
Hay veces que si no has utilizado .env,
a lo mejor ya lo tienes por arte de magia,
porque utiliza .env por debajo,
como por ejemplo lo que pasa con Next.js.
Next.js utiliza .env y ya te hace toda esta magia.
Entonces, lo que nos está pidiendo aquí es que hagamos nuestro propio .env.
Y está muy chulo porque aquí tienes que utilizar unas cuantas cosas
que están muy interesantes.
Dice, también se le puede pasar el path del archivo .env como parámetro.
O sea, puedes poner .env.config y pasarle el path de parámetro.
Cosas a tener en cuenta.
Solo se permite usar el módulo .fs para leer el archivo.
Si el archivo no existe, no debe dar error, simplemente no hace nada.
Si el archivo existe, no tiene ninguna variable de entorno, no hace nada.
Solo debe soportar el archivo .env o el que se le pasa como parámetro.
No hace falta de soporte .env.local.
Estos son cosas más avanzadas.
Las variables de entorno siempre son strings.
O sea, si esto es un número, un 2, 3, 4,
en realidad, cuando lo tengamos, será un 2, 3, 4 como un string.
¿Vale?
Esto lo simplifica bastante.
Pero ese .env es un objeto y, por lo tanto, es mutable.
Esto significa que podemos añadir propiedades nuevas sin problemas.
¿Vale?
Pues vamos a crear nuestro .env.
A ver, dice que tiene que tener un método config.
Así que vamos a poner aquí el config, export function config.
Le vamos a pasar aquí el path, que por defecto sea path con el .env,
por si no lo utilizamos.
¿Vale?
Si no le pasa a ninguno, que utilice el del .env para que nos lea el .env por defecto.
Si no, si le pasamos uno, pues lo tendemos.
Aquí vamos a intentar leer.
Vamos a hacer un try catch.
¿Vale?
Catch y aquí el error.
Vamos a intentar leer, por ejemplo, el contenido del archivo, del archivo .env.
Así que hacemos un import de fs from node fs barra promises.
¿Vale?
Vamos a leer las promesas.
O sea, vamos a leer del file system utilizando promesas.
Así que hacemos fs.readfile, le pasamos el path y le decimos utf8.
¿Vale?
La codificación, utf8, porque si no algunos textos, símbolos y tal, nos puede dar problemas.
Y aquí es donde tenemos que hacer la magia.
¿Vale?
Pero si hay algún error leyendo este archivo, vamos a poner un console error,
aunque entiendo que pone aquí, si el archivo no existe, no debe dar error,
simplemente no hace nada.
Bueno, pues a ver.
Vamos a quitar esto y ya está.
Ahora, también deberíamos hacer un export default donde devolvamos el config.
Esto es por si importan o podríamos crear aquí .env config y hacemos aquí un export default .env.
¿Vale?
Y así tendríamos tanto el soporte para los módulos de Macri como los de CommonJS.
Y así todo funcionando perfectamente.
Y si alguien trae el config directamente, pues perfecto.
Vale, la magia va aquí.
Aquí es donde va la magia.
Este ejercicio está muy chulo porque no solo estáis practicando un poquito de Node.js,
no solo estáis practicando un poquito de entender cómo funcionan estas cosas,
sino que también además tenéis que practicar JavaScript.
O sea, aquí tienen muchas cosas de JavaScript, muchas cosas de cómo funcionan las cosas en JavaScript.
O sea, por ejemplo, en el .env tenéis que leer cada una de las líneas.
Tenéis que leer las líneas.
¿Ves?
Aquí, dbhost, port y tal.
Vale, pues lo primero que tenemos, una vez que tengamos el contenido del fichero, que será todo esto,
y esto lo vamos a tener en un string, pues sería separar por cada una de las líneas.
Así que lo que hacemos primero es decir, vale, las líneas, vamos a hacer un .env.split y separamos por salto de línea.
Esto es básico, amigos, ¿vale?
Saber separar una cadena de texto por cada una de las líneas y transformarlo en un array,
esto es 1.01 de programación.
Luego no me digáis que no sabéis hacerlo porque entonces no estáis viendo el string.
Esto es básico, ¿vale?
Porque esto en casi todas las pruebas técnicas del mundo,
una de dos, o te hacen que transformes un array a un string, ¿vale?
Que es con el punto join o al revés.
Un string a un array y esto se hace con el punto split.
Es que esto es científicamente comprobado el 96% de las veces.
No tengo pruebas, pero tampoco tengo dudas, ¿vale?
O sea, es que de verdad, es que en todas las pruebas técnicas esto es súper típico.
Así que por favor, por favor, estos dos métodos os los tenéis que saber.
Tanto el join como el split.
En el join le podéis pasar cómo se tiene que juntar cada uno de los elementos,
que si no le pasáis nada, si no recuerdo mal, ¿es un espacio en blanco?
No, es una coma, es esto.
Creo que por defecto es esto.
Pero muchas veces, pues, ¿qué crees?
Queréis poner un espacio en blanco, queréis que esté todo pegado, lo que sea.
Y el split, pues, sería para separar a partir de un carácter.
En este caso, el salto de línea, ¿vale?
Y puede ser que sea, por ejemplo, con coma.
Queréis separar todos los que salgan con coma.
Lo que sea.
Pero por favor, por favor, por favor, por favor, tenéis que saber esto, ¿eh?
Entonces, aquí también lo mismo.
El split para separar cada salto de línea.
Y ahora lo que podemos hacer es que por cada línea, aquí tenemos cada línea, y empezamos a leer, ¿no?
Decimos, bueno, por cada línea que tenemos, tenemos la key, la asignación, y aquí estaría el valor, ¿vale?
Aquí hay una cosa que habría que tener un poquito de cuidado, porque si hacemos, ¿veis?
Aquí podríais poner, imagínate que tenemos esta cadena de texto.
Api key, igual, que es la asignación, y aquí tenemos la cadena de texto, pero fíjate que hay otro igual aquí.
Ojo, cuidado con esto.
No creo que lo tuviese en cuenta, pero claro, aquí alguien puede decir, vale, aquí tengo key value,
y en el valor lo que hago, la línea, la separo con el igual, ¿no?
Y normalmente esto funcionaría, pero entended que en este caso, fijaos, en este range es,
si tenemos esto, claro, si tenéis esto, imagínate que esto es el env, ¿no?
Env.
Y hacéis un env.split del igual, el problema es que os va a separar más de lo que esperáis,
porque vais a tener aquí la key, pero aquí vais a tener parte del value, y aquí parte del value, ¿vale?
A mí me parece un poco rizar el rizo, pero es verdad que puede ser algo bastante típico.
Así que lo que podríais hacer aquí sería hacer key, ¿ves? Este es el error.
Hacer esto, porque ahora el value no tiene lo que esperas, ¿vale?
¿Veis? Solo tiene parte, que es esta parte de aquí, porque ha separado por este igual,
por este igual, y ha dejado esta parte de aquí.
Lo que tendríais que hacer sería separarlos, todos los values, a la derecha.
Esto os dejará, obviamente, un array, pero no pasa nada, porque aquí ya lo que podéis hacer es join value,
y hacer un value.join, donde lo mezcláis, y ya tendríais aquí todos los valores seguros, ¿vale?
Y ya lo tendríais ahí.
Podríais hacer un join, un join, y justamente hacerlo así, también, claro.
Tendríais que hacer el join con el igual, para no perder el igual.
Pero ya está, con esto ya lo tendríais solucionado, y sería una forma.
Pero bueno, solo para que le deis al coco, porque esta pregunta os puede venir.
Os puede decir, oye, si ponéis un igual ahí, vosotros estáis ahí súper contentos, súper tranquilos,
no, pon un split y tal, y ven, ¡pain!
Y os pillan, vamos, bien pillado.
Así que tenedlo en cuenta, ¿vale?
Entonces, podéis hacer el join value, hacemos este value.join con el igual, ¿vale?
¿Y qué más?
Bueno, otra cosa a tener en cuenta, si tiene o no tiene las comillas, ¿vale?
Fijaos que aquí, a veces, puede tener comillas.
Ves que este puede tener comillas, este no tiene comillas.
Entonces, las comillas tendríamos que quitárselas.
¿Por qué?
Porque vamos a, esto lo vamos a leer como un string ya, directamente.
Y si lo guardamos correctamente, o sea, si esto lo dejamos así, fíjate lo que está pasando aquí.
Que tenemos doble comillas, porque tenemos la comilla de nuestra cadena de texto,
y por otro lado, las comillas que tenemos en el archivo de la variable de entorno.
Así que, lo que tendríamos que hacer aquí es, podrías hacerlo de diferentes formas,
yo lo voy a hacer más legible para que se lea correctamente, ¿eh?
Pero en el join value, podríais mirar, si empieza starts with con comillas,
¿vale?
Podéis hacer con estas comillas, con todas las comillas, ¿vale?
Pero bueno, esto lo dejo a vosotros ya, para que lo hagáis,
ahora que ya sabéis cómo se hace, pues que lo dejáis, lo veáis.
Podríais poner más, ¿no?
Si es con las comillas simples, con las dobles, pero bueno, solo para que veáis cómo se haría.
Y si tiene las comillas, pues aquí lo que tenéis que hacer, que el valor a guardar,
si tiene quotes, va a tener que ser el join value,
y le quitáis tanto el valor, el primero, y el último.
Y si no, le dejáis el que tengáis.
Y ya está.
Process.env, le pasáis la key, y aquí tendríais el value to store,
y con esto ya lo tendríamos.
Esta sería la magia.
Para cada una de las líneas, vamos viendo la key y el valor,
y entonces lo que hacemos es guardarlo en el process.env y la key que tenga.
Y esto es básicamente, esto no es todo lo que hace .env, ¿vale?
Pero esto es casi el 80% de lo que hace ese paquete, ¿vale?
Es más o menos el 80%.
¿No lo podrías hacer con replace?
Sí, se podría hacer con replace, se podría...
Pero me parece un poco innecesario hacerlo con replace, la verdad,
porque el problema del replace es que tendríais que hacerlo solo para el inicio y el fin, ¿vale?
¿Por qué? Porque tened en cuenta que aquí puede pasar esto.
Puede pasar esto.
No sé por qué este sale mal.
Pero el tema es que puede haber comillas dentro y además que estén escapadas, ¿vale?
O sea, tened cuidado porque con el replace os podéis cargar las comillas internas,
y entonces tenéis el mismo problema.
O sea, lo mejor que podéis hacer es aseguraros que las comillas que queréis cambiar son las de inicio y final,
porque si no, podéis liar la parda, ¿vale?
Entonces, tened cuidado porque hay muchas veces que puede ser correcto que haya una comilla por ahí por beta saber qué motivo.
Y de hecho, yo he visto muchas veces variables de entorno que se escapan, ¿vale?
O sea, que se utiliza el escape este justamente para eso.
Así que tengan cuidado con el tema de hacer un replace y olvidarte.
Podéis utilizar regex.
Yo paso de utilizar regex y es que estaría aquí todo el día.
Y al final esto me parece una forma un poco sencilla, porque al final es una prueba de junior trainee,
y estoy seguro que no esperan que te escribas una regex ahí en vivo y en directo.
Yo creo, ¿vale?
Pero esto al final sí que demuestra, al final tampoco tiene por qué ser así.
Por ejemplo, esto lo podrías hacer así, y esto lo podrías hacer, o sea, decir, vale,
si yo envalio es igual a cero, o sea, cero es igual a esto, ¿sabes?
O sea, yo creo que aquí lo que van a esperar no es que hagas el código más increíble del mundo,
sino que mentalmente entiendas el problema que te vas a encontrar.
Yo esto a lo mejor tampoco, sinceramente, si yo estuviese haciendo esta como entrevistador,
yo esto tampoco lo tendría en cuenta, ¿eh?
Esto ya me parece como de decir, ostras, lo ha tenido en cuenta.
O igual se lo preguntaría, oye, ten en cuenta esto, ¿cómo lo harías?
¿Vale?
Estos son típicas preguntas porque lo que quieren es ver tu pensamiento crítico y analítico.
Muchas veces decís, oye, ¿cómo mejoró mi lógica de programación y todo esto?
Este es el típico ejemplo de lógica de programación en la que en mitad de una entrevista te van a preguntar
y te van a decir, oye, y si tienes en cuenta este caso, ¿cómo lo harías?
¿Sabes? O sea, seguramente tú habrías ido, que con toda la razón del mundo, con esta solución, ¿vale?
Que no está mal.
Y entonces te dicen, oye, y si tiene comillas al principio, ¿entonces qué?
Entonces vas a tener que pensar y tal.
Así son las pruebas técnicas, ¿eh?
Vale, yo creo que esto funciona.
Tampoco tengo la seguridad, pero creo que esto funciona.
O sea, ¿cómo lo probamos?
Ah, vale, creo que tenemos test, así que vamos a ver los test.
Mira, .env.
Este debería ser el 6.
6.test.js.
Y solutions, creo que esto prueba ya unas cuantas cosas.
Vamos a ver si funciona y pasa los test.
Node.test.6.test.js.
Vale, dice expected undefined.
No sé si esto es porque yo, el .env no está haciendo exactamente lo mismo.
O mi prueba no estoy devolviendo correctamente algo.
A ver, try.config.test.
A ver, voy a eliminar este .env.
Y aquí dice limpiar el process, elimina el unlink este.
Load in file.
El config este sí que está aquí funcionando.
De hecho, se está llamando aquí.
Alguna cosa se me está olvidando.
A ver, a ver.
Ah, el read file este.
¿Veis?
Aquí se me ha olvidado.
Vale.
Vale, hostia, qué bueno es esto porque esto es pregunta de examen.
Es que esto no puede ser await.
Vale, qué bueno, qué bueno.
¿Ves?
Por eso son importantes los test.
Porque fijaos que aquí se me ha colado un problema.
¿Vale?
No me he comido el await.
De hecho, es que esto no puede ser await.
Esto no puede ser await.
Esto tiene que ser síncrono.
Ostras, claro, me imagino que por eso, por eso quieren que hagas esto.
Esto tiene que ser síncrono.
Esto tiene que ser sync.
¿Por qué?
Pregunta de, hostia, pregunta de entrevista, ¿eh?
¿Por qué?
¿Por qué esto tiene que ser síncrono?
¿Se os ocurre por qué esto tiene que ser síncrono?
Teniendo en cuenta todo lo demás, todo lo demás puede parecer que sea como contraintuitivo, ¿no?
Porque requiere variables de entorno.
Claro, el tema es que imaginad que hacemos esto.
Import config from .env, bueno, .env, nuestro .env, ¿vale?
.env, y hacemos config, claro.
Y aquí tú esperas process.env, dbhost.
El problema es que esto tiene que ser síncrono porque tiene que parar el flujo de ejecución.
Porque si no, esto podría ser undefined porque puede ocurrir una race condition si fuese asíncrono.
De forma que esta línea de código se ejecute antes de que termine esto que es asíncrono.
Entonces, podría alguien decir, bueno, pues haces aquí una await y ya está.
Y seguramente puedes tener razón, aunque el .env seguramente en su día no estaba pensado para utilizar la await
porque no existía el top level await.
Todavía no es compatible con todos, en todos los navegadores, todos los entornos de ejecución,
Node.js y todo esto.
Entonces, Node.js, a lo mejor si tienes Node.js 16 y no estás utilizando en más script modules,
estás utilizando todavía Common.js, esto no funcionaría.
Y claro, ya no vas a hacer esto.
¿Sabes?
Te imaginas todo esto.
Sería un poco rollo.
Entonces, por eso, haces esto síncrono, bloqueas ahí y ya está.
Entonces, alguien puede decir, y esto ya sí que sería, si ya sabes esto, si no encuentras trabajo es porque realmente no te da la gana.
¿Por qué no es preocupante que esto sea síncrono?
Porque esa sería, claro, alguien puede decir, vale, sí, entiendo por qué tiene que ser sync.
Pero, ¿por qué no pasa nada?
¿Por qué no es tan importante que sea síncrono?
¿Por qué se lo puede permitir que esto sea síncrono?
No debería ser, no es preocupante que sea síncrono.
No hemos dicho que en tema de rendimiento sería algo negativo, ¿verdad?
Bueno, pues no pasa nada que esto sea síncrono.
Síncrono porque esto se ejecuta una sola vez en toda nuestra aplicación.
La ejecución de este método solo ocurre una vez cuando iniciamos nuestra aplicación y a lo mejor pueden ser, yo qué sé, 0,5, 0,3 milisegundos.
Pero esto es solo al iniciar la aplicación.
No es una cosa que va a ocurrir en cada request de nuestra API o de nuestra aplicación,
sino que solo cuando arrancamos desde cero nuestra aplicación va a comerse este coste.
Entonces, como solo ocurre una vez, no es tan preocupante que sea síncrono, ¿vale?
Esto es importante porque muchas veces no entendemos el tema de que sea por qué hacemos las cosas asíncronas o síncronas.
Y aquí, pues tiene sentido que pueda ser síncrono porque no tiene un impacto negativo en el rendimiento al final.
O sea, el impacto es mínimo.
Así que, como solo se ejecuta una vez, no lo podemos permitir.
Pero si fuese esto que está en una función, por ejemplo, y yo qué sé, process request,
que esto se ejecuta en cada request, entonces sí que nos tendríamos que preocupar.
¿Entendéis?
Estas cosas son las que marcan la diferencia entre entender algo o que te suene.
Así que os recomiendo mucho que esto lo tengáis muy claro.
Y si no lo tenéis claro, que entendáis también cómo funciona el patrón módulo.
El patrón módulo, al final, muchas veces funciona así.
Por ejemplo, para que veáis claramente esto.
Mira, para que veáis claramente esto, y esto os va a volar la cabeza, y aunque seáis juniors lo deberíais saber.
Pero para que entendáis esto, os voy a explicar el módulo pattern muy fácil, muy fácil.
Hay seniors que no entienden esto, que no lo saben.
Imaginad que tenemos el módulo a.js y tenemos también el app.js y tenemos también el módulo otro.js.
Y vamos a hacer un npm init aquí para inicializar nuestro proyecto.
Y en el app.js, espérate, vamos a ponerle que esto es de tipo módulo para poder utilizar los inputs y todo esto.
Y esto va a volar la cabeza porque realmente es muy importante.
Vale, tenemos app.js, ¿vale?
Y aquí, pues, tenemos, vamos a poner console.log, vamos a poner iniciar la aplicación, ¿vale?
Iniciar la aplicación.
Pero vamos a importar aquí count from módulo a, ¿vale?
Vamos a importar el módulo a.
Que esto tiene aquí una función, export default function count.
Y esto lo que hace, pues, es decir, hola, ¿vale?
Y vamos a ponerle fuera cargado módulo a, ¿vale?
Y aquí, pues, el hola count.
¿Vale?
Importamos aquí el count módulo a.
Y también vamos a importar otro .js.
Y este otro .js lo que hace es también importar el count, ¿vale?
Y esto, pues, aquí podríamos hacer cargar otro .js, ¿vale?
Y aquí, cargado módulo a.js.
Cargar módulo a.js.
Vale, tenemos el punto de entrada de nuestra aplicación, ¿vale?
Y aquí, iniciar la aplicación, llamamos al count y lo llamamos cuatro veces, por lo menos, ¿vale?
Iniciar la aplicación, llamamos al count cuatro veces, pero, ojo, que aquí importamos el otro .js.
¿Veis este import de aquí?
Y esto lo que hace también es llamar al count dos veces.
La pregunta del millón es, teniendo en cuenta que el app carga al count y el otro también carga al count, ¿no?
Del módulo este.
La pregunta del millón será, ¿cuántas veces va a aparecer este console.log?
¿Cuántas veces sale este console.log?
Hay gente que dice cuatro.
Cuatro veces.
Una, una, ocho, una, dos, cinco, una.
Bueno, todo el mundo dice que una.
Una, una, una.
Bueno, veo que dos, dos, dos.
O sea, tenéis claro que una.
Mucha gente.
Cero.
Hay gente que dice cero.
Bueno, igual peta, entonces no saldría ninguna.
Gente que dice dos.
Vamos a verlo.
App.js.
Vale, pues, fijaos lo que está pasando aquí.
Carga en módulo A.
Carga el otro punto JS.
All account, all account.
Iniciar la aplicación.
All account, all account, all account, all account.
Solo ha aparecido una vez.
Pero si estamos importándolo dos veces, entonces, ¿cómo puede estar pasando esto?
Pues esto justamente es una cosa súper importante del patrón módulo.
Imaginad, imaginad que vosotros cada vez que importáis React, en realidad se estuviese evaluando todo el contenido de React.
Sería una verdadera locura.
Lo que está pasando aquí es que cuando nosotros hacemos un import del módulo, esta línea de aquí, al final, usa la misma referencia que importa aquí.
O sea, solo lo importa una vez, lo deja como en un mapa de memoria y cada vez que vosotros vais a importar este módulo, siempre utiliza la misma referencia, ¿vale?
No está utilizando, no vuelva a importar el módulo, sino que siempre utiliza la misma referencia.
Así que este console.log solo se ejecuta una vez, que además lo tenemos aquí.
Pero fijaos además lo que es interesante.
Lo más interesante es que este import que importa este módulo es lo primero que tenemos aquí.
Cargar módulo.
Luego importa este otro y este otro que va aquí.
Fijaos que importa el módulo, ya no enseña el console.log porque está utilizando la misma referencia y por lo tanto no vuelve a evaluar lo que sería este archivo.
Sino que ya lo tiene en memoria y dice, bueno, ya lo tengo en memoria.
Por lo tanto, este console.log no lo evalúo y esta función ya la tengo disponible en memoria.
Cuando alguien la quiera utilizar, pues ya la tendré.
Y aquí sí que tenemos el count, el count que lo tenemos justo antes de iniciar la aplicación.
¿Por qué?
Porque este contenido que ahora ya lo tenemos en memoria es lo que está trayendo aquí.
Y fijaos aquí que como lo que tenemos, ¿ves?
Este otro .js lo que tenemos aquí, digamos que esto lo transformaría en esto, que es lo que tiene memoria,
y este count que ya lo tiene, lo eliminaría.
Y así es como estamos viendo el proceso de toda la carga de los módulos.
Primero carga el módulo .js, luego el console.log de cargar otro, ¿ves?
Lo tenemos aquí, luego este count, luego este count, luego iniciar la aplicación, y ahora hola count, hola count, hola count.
La verdad es que está súper chulo el entender esto.
Os recomiendo un montón de que esto lo practiquéis, de que veáis cómo importan los módulos y todo esto.
Pero midi cuando se importa desde lugares diferentes, como cuando una aplicación tiene plugins y dependencias externas en esos plugins o paquetes,
si se refieren al mismo módulo, si se refieren al mismo módulo, va a ser lo mismo.
Es como React.
Imagínate, Gabriel, que tú tienes en tu aplicación React, import React from React.
Tú tienes este import React from React.
Import React from React.
Y tú tienes una librería, una biblioteca de terceros, que también hace esto, import React from React.
Pues lo importante es que si se refiere este módulo al mismo, van a utilizar el mismo, porque no tendría sentido cargar cuatro veces React.
O que cada vez que se haga un import, cargarlo otra vez, ¿entendéis?
Así que esto es muy importante que lo tengáis claro de cómo funciona el patrón módulo, que es como funciona básicamente JavaScript.
Node, test, 6T, vale.
Y ahora ya sí que está funcionando todas las variables de entorno, todos los tests y tal, ¿vale?
Así que solo nos quedaría el 7, el 7.test.js, nos quedaría el último ejercicio y ya lo tendríamos y habríamos superado totalmente las pruebas, ¿no?
Diseña una API REST utilizando Express.
¡Hostia!
Que permita a los usuarios crear, leer, modificar, actualizar y eliminar elementos de una lista.
La lista tendrá objetos que tienen la siguiente forma.
Haz la solución en el archivo Solution Server y exporta el API Server creado.
Instala Express con npm install express, no te preocupes por course, ¿vale?
Bueno, a ver, no es complicado, ¿eh?
¿Queréis que hagamos la API? Pues hacemos la API.
Lo primero que tendríamos que hacer, pues nada, import express from express.
Voy a ir un poco, os voy a ir explicando mientras lo hago.
Exportamos, ha dicho que exportemos la constante de app, que lo creamos ejecutando express.
Vamos a crear aquí items, vamos a tener un array de items con una ID y le ponemos un contenido, item 1.
Creo que esto era lo que he visto que en el test ejecutaba.
Vale, necesitamos, para que sea REST, tenemos que utilizar siempre como los mismos,
tenemos que utilizar los métodos de HTTP, el get, ¿vale?
Para recuperar cada una de las IDs, el post, el put, para actualizarlo, el delete, items.
Y yo creo que con estos ya os tendríamos.
Esto sea para recuperarlos todos, recuperar uno, crear uno, actualizar y borrar.
Así que ahora ya, app.get barra items y el callback con la request y la response.
Y aquí devolveríamos la respuesta como JSON de items.
Este sería para recuperarlos todos.
Ahora, para recuperar uno en concreto, items barra ID y aquí, rec res, para recuperar un concreto,
deberíamos encontrar la ID de la URL dinámica.
Esto es un segmento dinámico porque pasaremos barra items, barra y la ID.
Así que de rec.params y ahora pues hacemos un item found, items.find,
donde el item ID sea igual a la ID y hacemos return res JSON, el item found.
Esto sería para recuperar un elemento.
El más complicado yo creo que sería este, ¿no?
El post de items para crear un elemento en items.
Tenemos el rec y el response, ¿vale?
Tendríamos que recuperar el content de request.body.
Creo que tenemos que utilizar un middleware, luego lo vemos, ¿vale?
Y para recuperar esto, pues nada, creamos una nueva ID.
Voy a utilizar la longitud de los items.
Obviamente, esto lo estoy haciendo aquí porque entiendo que...
Entiendo que, o sea, no hace falta conectarse a una base de datos
y lo que quieren ver es que eres capaz de hacer el get, el get, el post, el put y todo esto, ¿vale?
Y hacemos el new ID sea más uno y el new item va a ser el ID, new ID y el content.
Y lo que hacemos es items.push de este nuevo elemento.
Y normalmente en temas de REST API, que si no sabes lo que es la REST API,
te recomiendo REST Middle Life, hicimos un directo...
Mira, solución de course y desarrollo de API REST con Express.
Y creo que en este explicamos qué es la REST API, por qué es importante, de qué se trata,
qué es lo que hace que sea REST y no sea REST.
Así que echan un vistazo.
Esto es parte de un curso de Node.js que tenemos, que tiene un montón, pero un montón de vídeos.
Así que mira, curso práctico de Node, de primeros pasos de API REST.
¿Ves? Pues aquí lo tienes.
Entonces, este sería el post y aquí lo mismo.
Normalmente en la REST API lo que hacemos es devolver lo que hemos creado, lo que hemos hecho y todo.
Así que, new item por aquí.
Nos faltaría el put.
El put sería actualizar, pues nada, barra, items, barra, dos puntos, el ID de lo que queremos actualizar.
Y aquí, pues igual, ID, recparams, const...
A ver, aquí podríamos hacer dos cosas.
Primero, esto lo vamos a tener que copiar, el content, porque vamos a querer actualizar con un contenido.
Y lo que tendríamos que hacer aquí es recuperar el item found.
Esto sería parecido a esto.
Solo que aquí vamos a hacer una mutación, ¿vale?
Vamos a hacer una mutación.
Item found, content, content.
Esto no lo hagas en producción.
A ver, esto lo estamos haciendo aquí porque no tenemos base de datos y esto funciona, funciona.
Pero obviamente esto no sería buena idea en un mundo real.
Yo esto lo explicaría en la entrevista.
Pero aquí yo entiendo que no tiene sentido preocuparse, porque al final, justamente lo que queremos.
En una base de datos se mutan los datos de la base de datos.
No es que borras y creas uno nuevo.
O sea, que esto sería lo más parecido que realmente pasa a una base de datos.
Return, REST JSON y el item found con ya la modificación.
Y nos faltaría el delete, que sería items, id, rec, ¿vale?
Esto sería para borrar el item.
También recuperamos otra vez la id, rec.params.
Y aquí lo que deberíamos entender, tendríamos que recuperar el índice del item que encontremos.
Item, item.id, igual id.
Tendríamos el índice y lo que tenemos que utilizar es el splice para modificar.
Splice, le pasamos el item index y le decimos que queremos eliminar uno.
Y aquí vamos a devolver el status 200.json, porque tampoco hay nada que...
No hace falta devolver nada.
Y solo nos faltaría crear el servidor, server, app.listen y el puerto.
En este caso, bueno, lo típico que se hace es process and port y si no, 3000, ¿vale?
Y ya está.
Aquí le podéis poner el típico callback de si está escuchando en algún sitio y tal,
pero bueno, ¿quién le importa?
Si lo importante es esto.
Y ya está.
Con esto hemos hecho la API REST.
A ver, puede haber algún error porque lo he hecho así, pim, pam, pim, pam, uno detrás del otro.
Vamos a ver si se me olvida algo aquí.
Hace la solución.
No te preocupes por course, ¿vale?
Vamos a probar con los test y ahora me enteraré si tenemos algún problema.
Ojo, que me dice...
No puede resolver la dependencia de TypeScript.
¿Cómo que TypeScript?
¿Qué es esto de TypeScript?
Fuera TypeScript.
¿Vale?
Express, mpm install.
Vamos a instalar eso.
Que necesitamos express.
Esto de TypeScript, que al final no es necesario.
O sea que...
¿Vale?
Tenemos aquí el servidor.
Ejecutamos el test del 7, que entiendo que es el del servidor.
Vale, ya empiezan los errores.
Vale.
Vamos a ver.
Vamos a ver qué problemas tenemos.
No puede estructurar content de rig body as...
Porque es undefined.
¿Vale?
Esto me lo imaginaba y esto es porque en el post, ¿veis que estamos haciendo esto?
Esto es porque por defecto no podemos leer el body de la request.
Para hacer esto y que te lo transforme en un JSON, necesitamos un middleware.
Así que aquí tenemos que utilizar el use de express.json.
Por suerte esto es una cosa que ya viene en la biblioteca y lo que hace es que cuando le enviamos al hacer un post el body,
lo que hace es transformarlo automáticamente en JSON para que podamos acceder fácilmente desde request.body cuando hacemos esto.
¿Ves?
Entonces ya sí que podremos hacer esto.
Si no, este body no tiene nada.
¿Vale?
O sea que primer problema solucionado.
Vamos a seguir por aquí.
¿Vale?
Veo que todavía hay problemas.
A ver.
Para arriba.
Vale.
Debería añadir un nuevo item.
Dice expected values to exit equal.
Undefine test item.
¿Vale?
Veo que el delete sí que funciona, pero hay algunos que no funcionan del todo.
¿Vale?
¿Qué está pasando en el add a new item?
Vamos a ver el de add a new item.
Add a new item.
Que sería el post.
El post nos dice que no está creando...
A ver, os voy a leer porque seguro que en el chat seguro que alguna cosa me habéis contado.
¿Por qué el uso del operador interrogante y no el de tal?
Este uso del interrogante.
Este tiene más sentido utilizar aquí porque imagínate si le pasas el puerto 0, por ejemplo, y haces esto.
Esto estaría mal y el que tomaría sería el 3000.
Lo cual es incorrecto.
El operador correcto sería este.
Que revisa que puerto sea nullish.
O sea, sea nullish, sea null o undefined.
Ah, y verdad.
Que siempre que digo middleware la gente es middleware.
Perdón, ¿eh?
Perdón.
Perdón, que sí, que luego en los comentarios de YouTube se me va a poner la gente.
Ay, dicho middleware, no sé qué.
Es verdad.
Me estáis comentando que esto es find index y tenéis razón.
Mira que lo he comentado pero no lo he escrito, ¿vale?
Pero esto para que veáis que muchas veces uno escribe mientras está ahí a saco y entonces no le da la cabeza.
Vale.
Entonces, no creo que sea solo ese problema porque también me falla el add a new item, ¿no?
Dice, esperaba que fuese...
En el post que dice new item, el push, res, json, new item.
Vale.
También debería haber los test, ¿no?
A ver qué es lo que espera.
Cuando añadimos un nuevo item, aquí tenemos el contenido.
Contenido, item ID.
Ah, mira.
Es que hace un get.
Ah, ya sé lo que es.
Ya sé lo que es.
Mira.
Lo que está pasando, está fallando este get.
¿Por qué está fallando este get?
Vale.
Ya sé lo que está pasando.
Lo que está pasando es que cuando nosotros le pasamos una ID en la URL, lo que está pasando muchas veces es que, fíjate, tú cuando entras a una URL, localhost 3000, api, items, 123, claro, el 1234, aunque tú lo ves como un número, en realidad es un string, es una cadena de texto.
Esto es un error que me suele pasar mucho.
Entonces, esta ID, aunque tú mentalmente piensas que es un número, en realidad es una cadena de texto.
Por lo tanto, aquí estamos utilizando números, pero aquí lo que le llega es una cadena de texto.
Podríamos transformarlos así con un number.
Lo peor que puede pasar es que al final nos devuelva ahí un none.
Podéis utilizar un are operator si os gusta más, ¿vale?
Yo no soy muy fan.
O sea, a mí me gusta más utilizar el number, pero bueno, solo para que lo sepáis, esta locura se puede hacer, ¿vale?
Bueno, locura no, es el operador un ario, tampoco es tan locura.
De hecho, funciona un pelín diferente al number en algunos casos, pero podéis hacerlo así o lo que yo recomendaría sería hacer más bien esto, ¿vale?
¿Por qué? Porque me parece más legible.
Y puede ser que por aquí vayan los tiros de los problemas que estaba teniendo.
Ahí lo tenemos.
O sea, ya teníamos la REST API y yo creo que esto, esto, la verdad es que sí que es algo que, hombre, con algunos problemitas que podéis tener,
pero sí que os recomiendo que esto sepáis hacerlo.
O sea, saber hacer una REST API desde cero con Express y tener en la mente el tema del put, el delete, el post y cómo lo haríais cada uno,
esto, por favor, practicarlo porque esto es muy típico y esto al final, bueno, ya veis que en esta prueba técnica lo piden, lo preguntan,
es el ejercicio más grande y la verdad es que es que te puede costar si no tienes muy claro cómo hacerlo, ¿vale?
Entonces, no digo que lo memoricéis, pero sí que lo practiquéis, que lo entendáis y que llegado el punto no os cueste,
porque si no este tipo de cosas os puede marcar un poco la diferencia entre pasar una prueba y no pasarla.
Y es muy fácil esto, o sea, esto son 50 líneas de código, yo creo que lo debéis hacer.
¿Por qué no utilizas ParsSynth?
El ParsSynth es el último que utilizaría y es el menos recomendable porque se puede hacer con Numbers y creo que queda mucho mejor.
Ya no se usa el Recovery Node, efectivamente, Arturo, esos que no han venido al curso Node.js, pero lo explicamos.
Require ya no se, sí que se utiliza Node.js todavía porque es imposible quitarle la compatibilidad de golpe,
pero no es recomendable que lo utilicéis, mejor hay más grid modules, ¿vale?
¿Por qué en el Splice, en el Delete y no Filter?
Bueno, como he explicado antes, el hecho de hacer un Filter sería devolver un nuevo array, ¿vale?
Entonces, la verdad es que si lo que hacemos es simular una base de datos, tiene más sentido mutar el array original
porque una base de datos, tú no recreas la base de datos cada vez que haces un Delete,
sino lo que haces es mutar el contenido de la base de datos.
Entonces, por eso utilizo el Splice en el Delete y no utilizo un Filter,
porque no quiero volver a recrear una nueva lista, sino que lo que quiero es mutar lo que hay y ya está.
Eso es mi opinión, pero tiene sentido si lo queréis hacer de otra forma.
¿Por qué te funcionaba el test del Delete si no tenía un Find Index?
Bueno, seguramente porque lo ha hecho bastante pirata, ¿no?
Aquí al final ves, independientemente si lo encuentro, aquí lo que debemos hacer es,
si no lo encuentro, si el Index es menos uno, entonces hacemos un RensReturn404.json.
¿No? Teníamos que hacer esto. Y luego si no, pues entonces hacer esto.
Esto tendría más sentido. Se me ha olvidado un poco hacer los 404, que tendría sentido.
Por ejemplo, aquí también. Si no hemos encontrado, si el ItemFound, si no lo hemos encontrado,
¿vale? Si no hemos encontrado esto, hacemos un RensStatus404.json es simplemente para siempre devolver un json.
Y esto es lo que deberíamos hacer. Nos faltaría un poquito de validación, pero he entendido que no nos están preguntando por nada de validación.
O sea, igual luego nos preguntan y nos van añadiendo cosas, ¿no?
¿Verdad no nos vemos?
¿Verdad?
¿Verdad?
¿Verdad?