This graph shows how many times the word ______ has been mentioned throughout the history of the program.
Vale, dicho esto, decorators.
Hablemos de decorators, qué son, para qué sirven
y por qué son tan interesantes, cómo funcionan
y sobre todo, y lo más interesante para mí, en mi opinión,
cómo crear uno.
Porque eso es una cosa que pocas veces se ve,
porque muchas veces es cómo utilizarlos, pero no cómo crear uno.
Si queréis saber más de decorators y tener toda la documentación,
tenéis esto de Propulsar Decorators.
Este es el repositorio del TC39,
que son los que se aseguran que llegan ciertas specs,
nuevas features al lenguaje de JavaScript.
Y aquí tenéis toda la explicación técnica con ejemplos y todo esto.
Los decoradores, a día de hoy, ya están en la fase 3,
tenlo en cuenta, ¿vale?
Aunque aquí ponga fase 2, justo van a pasar a la fase 3.
Los decoradores son una funcionalidad que lleva muchos,
pero muchos años trabajándose para JavaScript
y no es una cosa que sea solo de JavaScript.
Por ejemplo, en Python tenemos decoradores
que funcionan bastante similar a cómo funcionaría en JavaScript.
Similar, pero no exactamente igual.
En PHP tenemos anotaciones.
En RAS tenemos anotaciones.
Hay un montón de lenguajes que tienen un concepto,
si no igual, bastante similar a los decorators.
Dicho esto, antes de empezar,
tened en cuenta una cosa.
Una cosa es el patrón decorador
y otra cosa es la funcionalidad de los decoradores.
¿Por qué es importante?
Porque aunque es verdad que el patrón decorador
lo puedes hacer con la sintaxis de los decoradores,
tened en cuenta que el patrón decorador
podrías hacerlo sin la sintaxis de los decoradores, ¿vale?
Es un patrón.
Entonces, hay que diferenciar la sintaxis con el patrón.
Es como programación funcional,
hay que separarlo de la sintaxis de la función, ¿vale?
Para que nos entendamos.
Porque muchas veces la gente,
cuando hablamos de decorators,
directamente me vienen patrón decorador.
Vale, ok.
Son dos cosas que están relacionadas,
pero no son lo mismo directamente.
Puedes hacer decorators,
que tendrías el patrón,
te estaría forzándolo y tal,
pero no hace falta que pienses tampoco muchas veces
en el patrón decorador, ¿vale?
Y de hecho, no necesitas utilizar decoradores
para hacer el patrón decorador.
En fin, esto te lo dejo muy claro,
especialmente si lees por ahí patrón decorador
y te crees que es lo mismo.
No es exactamente lo mismo, ¿vale?
Entonces, ¿qué son los decoradores en JavaScript?
Los decoradores en JavaScript
es una propuesta que han puesto en el lenguaje
que te va a permitir extender las clases
y no solo lo que sería la referencia de la clase,
sino que estamos hablando de métodos de clase,
propiedades de clase, los getters, los setters,
los accesos, que es una cosa nueva,
pero bueno, en esto no entraremos en detalle.
Y lo que nos permite es justamente,
al extender esto,
es añadirle funcionalidad,
cambiar su funcionalidad,
o incluso reemplazar el valor
que iba a dar esa funcionalidad de la clase.
Con los ejemplos lo vamos a ver súper claro.
Aquí tendríamos un decorador.
El decorador se define con la arroba al principio,
¿vale?
Con esta arroba que veis aquí.
Y como puedes ver, en este caso,
esto sería un decorador
que afecta a toda la clase.
Importante, los decoradores afectan a clases,
a métodos de clase, propiedades de clase,
y ahora propiedades de clase, ¿y qué más?
Bueno, todos los elementos que tengas que tener en una clase,
¿vale?
Incluso métodos estáticos.
Pero no a funciones.
Tú no puedes decorar una función.
Pero el decorador en sí es una función.
Tenlo en cuenta,
porque luego podríamos traducir
los decoradores que vamos a crear.
Al final son puras y simplemente son funciones.
Son funciones.
Un decorador es una función.
Cuando lo escribamos aquí,
que tengo aquí el playground,
que por cierto es bastante interesante este playground,
y te explicaré por qué necesitamos un playground, ¿vale?
Así que vamos a ver.
Aquí tenemos dónde puedes utilizar el decorador.
En las clases, como hemos visto.
En los campos de clase,
en los que sean públicos, privados o estáticos,
los métodos de clase y los accesos.
Que esto es una cosa nueva,
que básicamente lo que te hace son como las fields,
pero que te hace automáticamente el getter, el setter,
y te deja la propiedad privada.
Pero bueno, esto no es importante.
No te preocupes.
Se parece un poco a Java,
se parece un poco a Spring,
pero vais a ver que tienen un poquito cosas diferentes.
Respecto a la pregunta de cuándo estarán disponibles los decoradores,
yo creo que a lo largo de este año,
o a principios del que viene.
Pensad que llevan muchos años, no sé si 5 o 7 años,
trabajando los decoradores es una cosa que ha cambiado mucho.
Que por cierto, antes de continuar,
los decoradores ya están en TypeScript,
pero los decoradores de TypeScript no son exactamente igual
a los decoradores de JavaScript.
¿Ok?
Pero aún así, los decoradores son una funcionalidad de JavaScript.
Lo que pasa es que todavía no han llegado de forma oficial al lenguaje.
Lo digo porque hay gente que cree que los decoradores son de TypeScript y ya está.
Lo que pasa es que TypeScript se adelantó,
implementó un tipo de decorador
que se parece bastante,
pero no es exactamente igual.
Esto el día de mañana puede traer problemas, justamente.
Pero bueno, esperemos que no mucho.
Venga.
Dicho esto, venga, vamos a hacer un ejemplo desde cero,
para que lo veamos claro.
Si tenemos nosotros una clase,
vamos a poner, yo que sé,
una clase como...
Una clase normal y corriente.
¿Vale?
Vamos a poner clase persona.
Ponemos una clase, ¿no?
Esta clase, pues ahora mismo no tiene ninguna historia.
Para decorar, ¿qué podríamos hacer?
Podríamos sacar aquí y voy a poner logger.
Vamos a crear un decorador.
Voy a hacer esto un poquito más grande,
porque lo veamos bien.
¿Vale?
Vamos a poner un decorador aquí, que es logger.
¿Cómo creamos el decorador para empezar?
Pues tenemos que crear como una función, ¿vale?
Así que vamos a crear la función.
Voy a poner esto por aquí, para que os lean mientras.
¿Vale?
Creamos nuestra función logger.
La creamos aquí.
Los decoradores, súper importante,
que son funciones.
Punto y pelota.
Y ahora que tenemos esta función aquí,
va a llegarle dos parámetros.
Uno, el valor.
Y el otro, el contexto.
Por ahora, lo único que voy a hacer en esta función,
voy a hacer aquí console.log,
voy a llamar decorator.cold, ¿vale?
Para ver si se ha llamado.
Le voy a dar aquí al botón este de ejecutar.
Vale.
Fíjate en una cosa.
Yo, aunque todavía no he creado una instancia de la clase persona,
¿qué pone aquí?
Decorator.cold.
Esto es súper importante que lo tengas en cuenta.
Las funciones de los decoradores, ¿vale?
Los decoradores se ejecutan en el momento en el que se evalúa la clase,
no cuando se instancia la clase.
Esto es súper importante porque lo que vas a poner aquí dentro
se va a ejecutar en cuanto se evalúe este código.
No cuando se instancia,
no cuando tú hagas un new persona, igual new persona, esto, ¿vale?
No cuando hacemos esto,
sino directamente cuando se evalúa esto.
Esto es súper importante.
Dicho esto, ahora que tenemos aquí,
que ya sabemos que se está evaluando,
podríamos ver tanto qué tiene el value, ¿vale?
Así que vamos a poner aquí el console.log,
vamos a ver value y context y le damos a ejecutar, ¿vale?
He hecho algo porque se me ha quitado esto, perfecto.
Pues aquí, ¡pum!
Tenemos que nos dice,
el value nos pone aquí como una function.
¿Qué significa esta function?
Ya te digo yo lo que me va a dar.
Este value que tenemos aquí,
este value de aquí,
nos va a devolver la clase.
¿Por qué?
Porque normalmente el primer parámetro de los decoradores
nos va a devolver lo que estamos decorando, ¿vale?
Ya veremos que hay una excepción,
no siempre te devuelve el value
cuando haces la propiedad de clase,
porque no tiene mucho sentido,
pero cuando es el método de una clase
o cuando es la propia clase,
pues aquí en value tendríamos la propia clase, ¿vale?
Esto sería la...
Voy a poner class con K para que no pete, ¿vale?
Pero esto sería el class.
De hecho, este class aquí podríamos hacer,
para que te hagas una idea,
podríamos hacer esto, new class.
Y este class sería persona, ¿vale?
Así que, por ahora vamos a dejar como teníamos.
Le ponemos value.
Value.
¿Se ve bien el código?
¿Sí?
Sí, sí, sí.
¿Sí?
Vale.
Vale.
Venga, vamos a seguir.
¡Ay!
Esto se me ha escapado.
Esto aquí, esto aquí.
Vale.
Vale, pues ahora que tenemos esto,
vamos a seguir continuando con el logger.
Luego veremos cómo utilizamos este logger,
cómo le podemos añadir.
Pero ahora ya sabemos que aquí podríamos hacer cosillas.
Voy a enseñarte primero todos los ejemplos
donde puede ir el logger,
solo para que veas un poco el ejemplo
de lo que vamos a tener aquí de información.
Estoy decorando ahora la clase,
pero podríamos decorar, por ejemplo,
¿vale?
Una propiedad pública.
Pongamos, yo que sé.
Pues esto, persona.
Pues vamos a poner que sus kilos son 75, ¿vale?
¿Y cómo podríamos decorar esto?
Pues solo tenemos que ponerlo justo encima.
Ponemos aquí logger, ¿vale?
Entonces, lo mismo podríamos hacer.
Este logger lo podríamos poner, por ejemplo,
también en un get, ¿vale?
Esto sería un método de la clase.
Pues aquí podríamos tener esto
y esto tendría que hacer esto.
Luego, ¿dónde más podríamos hacerlo?
En los getters y en los setters.
Por ejemplo, get.
Este no tenía mucho sentido.
Voy a llamarlo en castellano, ¿vale?
Para que lo veamos claro.
Y esto, igual, lo podríamos...
Vamos a poner esto.
Esto sería un getter.
Y también lo podríamos poner en un setter.
Hay una cosa importante de los setters y los getters
que a veces causa problemas.
Y es que la gente se cree,
como los getters y los setters a veces van juntos,
se creen que si tú pones un decorador aquí,
esto afecta tanto al getter como al setter.
Y esto no es así.
Tienes que ponerlo en los dos, ¿vale?
Tanto en el getter como en el setter.
Si no, uno estará decorado y el otro no estará decorado, ¿vale?
Ponemos esto y aquí le asignamos esto, ¿vale?
Y ya estaría.
Vamos a darle a ejecutar a ver si va todo bien.
Vale, perfecto.
Aquí pasan diferentes cosas, muy interesantes además.
Pero, bueno, no vamos a entrar en muy detalle
porque una cosa muy interesante aquí sería el orden
en el que se están ejecutando, ¿sabes?
O sea, cuál es el orden en el que se ejecutan los decoradores.
Entonces, veríamos aquí que tendríamos el kind este.
Fíjate que tenemos un undefined.
En el kind es el que, en el contexto,
este contexto es este objeto de aquí.
Y esto, este objeto nos va a dar bastante información
de qué es lo que estamos decorando.
Por ejemplo, gracias a este objeto sabemos el kind.
El kind nos dice que es el field.
Y por lo tanto, lo que está haciendo es este.
Este sería el field, ¿vale?
Este sería la decoración del kind field, ¿vale?
Y de hecho, fíjate que me dice el nombre es weight.
Y es que aquí lo tenemos, weight.
Y ya nos da más información.
Si es estático, si es privado, pero no es estático ni privado
porque no pone nada, es público.
Y ya está, ¿vale?
Tenemos el get metadata, set metadata, ¿vale?
Luego tendríamos, siguiente, el method.
Este sería el siguiente, ¿no?
Kind method.
Este sería el kind method.
Name set.
Y ya, ¿no?
Name set.
Vale.
Fíjate, fíjate en una cosa.
Aunque pone method, aunque pone method, no se refiere a este.
Se refiere a este.
¿Vale?
¿Y por qué lo sé?
Porque aunque el kind pone method, el name pone set.
Y el único set que tengo aquí es este.
Esto es porque yo me he equivocado.
Y en lugar de haber puesto set así tal cual, tenía que haber puesto set peso.
Y entonces no me hubiera pillado esto como un method.
Se me hubiera pillado como un setter.
¿Vale?
Entonces, ahora vamos a darle a ejecutar otra vez para arreglar esto.
Y ahora sí que vemos kind setter.
Ahora sí que está bien.
Name peso.
Ahora sí que está pillando este.
Y este, el kind es setter.
Y aquí el kind es getter.
¿Vale?
Kind getter.
Y finalmente el method sería el último.
Así que esta información, este sería el method.
Esta información del tipo de lo que estamos decorando,
tenemos esta información aquí, ¿vale?
Así que aquí ahora ya podríamos como hacer diferentes cosas dependiendo de qué es lo que estamos decorando.
Ahora, una cosita rápida para que tengas clarísimo.
El primer valor.
¿Te acuerdas que te dije que el primer valor es el que nos va a indicar?
Ah, mira.
Por cierto, que no he dicho último.
El kind class.
El kind class, el último que se ejecuta es el decorador de la...
Este.
¿Vale?
Que este es kind class.
Y es el último que se ejecuta.
O sea, que este sería el primero.
Para que lo tengamos claro.
Este sería el primero.
Este sería el segundo.
Este sería el tercero.
Y este sería el cuarto.
Y este sería el quinto.
¿Vale?
¿Es importante el orden?
A ver, no es importante para ti, pero obviamente internamente para JavaScript es bastante importante.
Porque si no tuviese este orden, podría haber problemas a la hora de cómo funciona.
¿Ok?
Pero aún así, para que lo tengas en cuenta, este es el orden en el que se van a estar ejecutando.
Dicho esto, ¿por qué es importante también el primer valor?
El primer valor, como te decía, te devuelve lo que está decorando.
Pero fíjate que en el primero, el primero, que es el fill, es undefined.
Este no te devuelve en el value, no te devuelve nada.
¿Por qué?
Porque no sería capaz de devolverte el propio fill.
O sea, no sabe...
No te va a devolver ni el valor.
No te va a devolver 75.
No te va a devolver weight.
O sea, no te devuelve nada.
Te devuelve undefined.
Esto es el único en el que vas a tener este caso.
Por ejemplo, en el setter, ¿ves que aquí pone function?
¿Por qué?
Porque está devolviendo esta función de aquí.
¿Vale?
Esto que tengo aquí seleccionado es justamente esta función que tenemos aquí.
Si sigo bajando este getter, esta función, sería esta función que tenemos aquí.
¿Vale?
Y así, igual, este method, este function, sería esto.
¿Por qué es importante esto?
Obviamente, porque al tener la función, lo que vamos a poder hacer es ejecutarla y cambiarle comportamientos.
O vamos a poder reemplazarla directamente.
Vamos a poder recuperar lo que ejecuta, hacer algo después de la ejecución.
Vamos a poder hacer un montón de cosas.
¿Vale?
Así que ya tenemos aquí un montón de información justamente para trabajar con esto, para decorar el método de nuestra clase.
¿Vale?
Ahí, hasta aquí, ¿todo bien?
¿Todo correcto?
¿Sí?
Bueno, vamos a hacer algo.
Vamos a quitar todos estos porque no son muy interesantes.
O, mira, lo vamos a hacer de otra forma, más fácil.
En lugar de quitarlos, los vamos a dejar.
Y lo que podemos hacer aquí, en lugar de poner el console.log, es poner un if.
¿Qué tienen que hacer los decoradores?
Los decoradores tienen que cambiar justamente el comportamiento de lo que están decorando, si quieren.
O sea, pueden expandirlo, lo pueden reemplazar,
o lo pueden evitar, pueden hacer lo que quieran.
Entonces, lo que podemos hacer aquí es decir, voy a mirar, ¿no?
Si el kind es igual al method, esto significa que sería este, este de aquí, ¿vale?
Pues le voy a cambiar el comportamiento, ¿vale?
Vamos a cambiar el comportamiento de este método.
¿Qué es lo que podemos hacer aquí?
Pues tenemos que devolver una función, porque tenemos que devolver un igual, ¿no?
O sea, ¿qué es lo que estamos decorando?
Una función.
Pues, ¿qué es lo que tengo que devolver?
Pues una función, ¿vale?
En el caso que el kind fuese class, tendría que devolver una clase, ¿vale?
Pero en este caso es un method.
O ya en el caso de los setters y los getters también sería una función, debería devolver una función.
Así que en este caso vamos a hacer un function y vamos a devolver,
vamos a hacer que el parámetro sean todos los argumentos y aquí dentro es donde vamos a hacer un poco nuestra magia.
¿Qué podemos hacer?
Bueno, aquí vamos a hacer algo sencillo.
Por ejemplo, vamos a hacer login, ¿vale?
¿Qué podemos recuperar de aquí?
Podemos recuperar aquí en context hemos visto que teníamos el nombre, ¿vale?
O sea, que vamos a recuperar el name y vamos a recuperar el kind.
Entonces vamos a poner login name execution, ¿vale?
O sea, vamos a saber cuál es la función que se ha ejecutado y podemos incluso recuperar with arguments
y podemos poner aquí los argumentos, ¿vale?
Join, vamos a poner con coma.
Vamos a saber con qué argumento se ejecuta el método.
Vamos a ver que no hay ningún argumento porque va a estar vacío, pero bueno, nosotros lo podríamos forzar.
Esto es el console.log.
O sea, ya estamos decorando porque estamos añadiendo algún tipo de funcionalidad.
Luego, además, podríamos llamar al propio método que tenemos en value, que sería el getWade.
O sea, podríamos ejecutar el método.
¿Cómo lo hacemos?
Gracias al value.
Aquí tendríamos lo que devolvería el return value, ¿vale?
¿Cómo lo ejecutamos?
Pues tenemos que hacer value.call, llamamos esto y le pasamos el this.
¿Por qué?
Porque necesitamos asegurarnos que el contexto de ejecución sea el de antes.
No hace falta que esto lo entienda.
Sé que os da pánico el this.
Una vez me puse a explicar el this y la gente se fue corriendo y tal.
No te preocupes.
Esto es un patrón súper...
Que si lo recuerdas, es todo lo que tienes que saber.
Que cuando tienes que llamar al método este para ser...
Sí, sí, con el this se fueron todos.
Pero lo único que tienes que saber es que tienes que llamar la función con el contexto de ejecución del this.
Porque si no, no te aseguras que lo estás llamando correctamente.
Pero con que esto te acuerdes que lo tienes que hacer así, no pasa nada.
Ya está.
Ya está.
Ya pasó.
¿Vale?
Entonces, ya está.
Todo el mundo, ah, no, el this, el this.
Sí, y luego, ¿y cómo me hago senior?
¿Sabes?
Ah, this, no.
¿Y cómo me hago senior?
Es que la gente es la hostia.
Vale.
Y luego, finalmente, lo que podríamos hacer, pues, podemos hacer un montón de cosas.
Podríamos aquí, end execution after returning...
Este, el return net value.
¿Vale?
Lo podemos hacer así.
Y podríamos devolver el return net value.
Pero ahora vamos a ver que incluso vamos a poder hacerle más cosillas.
Vamos a probar si esto funciona.
Y para poder probar esto, claro, si yo ahora le doy a execute, no me sale nada en la consola.
Y dices, pero ¿por qué no sale nada?
Bueno, no sale nada porque no estamos ejecutando nada.
Sí que se ejecuta esto.
Ya verás que si esto lo pongo aquí, console.log, esto ponemos aquí, decorator.cult, va a salir de esto unas cuantas veces.
¿Vale?
Tres, cuatro, cinco.
¿Por qué?
Porque tenemos el decorador cinco veces.
Pero como el decorador devuelve una función, esta función que devolvemos no se ejecutará hasta que no ejecutemos realmente en una instancia este método de aquí.
¿Vale?
Importante diferencia.
Esto se ejecuta en evaluación, ¿vale?
O sea, cuando evalúa la clase, cuando entra aquí la sintaxis, lo evalúa, lo ejecuta.
Pero esto, esto de aquí, se ejecuta cuando llamemos al método.
¿Vale?
Importante.
Esta función de aquí no se ejecuta.
Es que aquí también hay mucha gente que se hace ya pichado lío.
Pero muy fácil.
Esta función de aquí, el juego se ejecuta en evaluación cuando se está compilando, interpretando el código.
Pero esta de aquí, solo cuando llamemos al método.
¿Vale?
Importante.
Aún no le veo utilidad.
A ver, hay otra cosa que hay mucha gente que se vuelve loca.
No hace falta tampoco que a lo mejor utilicéis los decoradores.
A lo mejor vuestro día a día no necesitáis decoradores.
Pero lo cierto es que hay un montón de librerías, un montón de posibilidades con los decoradores.
Y uno, conocerlos es súper importante.
¿Por qué?
Porque es parte de la sintaxis y va a ser parte muy importante de la sintaxis.
Que ahora que encima los acabáis de conocer, no le veáis utilidad, es que es normal.
Yo la primera vez, la primera vez que vi y pasaron por mis ojos React, ¿sabes lo que me pasó con React?
Que no le vi utilidad.
Y pensé, pero qué tontería, si yo con Backbone puedo hacer esto y lo otro y no le vi utilidad.
Entonces, a mí históricamente, lo que me ha demostrado el mundo y la vida, es que aunque tú no le veas utilidad,
tienes que tener las orejas bien puestas, porque igual un día le encuentras la utilidad.
Y aunque tú no le encuentres la utilidad, sí que es verdad que es importante conocerlo,
porque de repente te puede estallar, que lo tengas que utilizar, que lo tengas que dominar,
que tengas que arreglar un decorador, estas cosas pasan.
Así que no luchéis contra ello.
Directamente, abrázalo.
¿Tienes parámetros como TypeScript?
No.
Eso se va a quedar exclusivo por ahora de TypeScript.
No te metas con la comunidad de React.
Con el realidad de la comunidad, pero sería así el primero.
Pues es la función que está retornando y la que se llama en ejecución.
Exacto.
Esto en SGS ya lo tiene, incluso tiene interceptos.
La diferencia es que esto será nativo JavaScript.
Claro, efectivamente.
Pero yo os estoy explicando cómo crear un decorador.
Claro, en Nest ya os viene.
Entonces, lo que os quiero es enseñar justamente.
Es como los proxies.
No tienen mucha utilidad en una aplicación cualquiera, pero son el core de Vue.
Efectivamente, Hallibur.
Ahí está.
Y luego también es que los decoradores...
Aquí hicimos un ejercicio con proxies, que fue bastante chulo,
y la gente dijo, ostras, pues de repente.
¿En qué ocasión es útil o necesario usar clases en JavaScript?
Guau, eso me daría para un mundo entero.
Pero muchas veces cuando, por ejemplo, quieres o cuando quieres un singleton
o cuando quieres tener el código bastante recogido.
Hay algunas veces que sí.
¿Vale?
¿Hay algún proposal de tipos de datos de like JavaScript en JavaScript?
TypeScript en JavaScript.
Hay uno de types como comentarios.
Yo hace años dije, ¿qué tontería esa de que Flash está muerto?
Ya te digo, ¿eh?
Me parece súper top que estés contando decoradores de verdad.
Bueno, esa era la idea.
Venga, seguimos un poquito.
Que de verdad que es que creo que es súper importante.
Y mucha gente tiene mucho miedo a los decoradores.
Y no es para tanto, ¿vale?
No es para tanto, os lo juro.
Vale, ya hemos creado este decorador, ¿no?
Y dices, vale, si el tipo es method, hago esto.
Vamos a ejecutarlo.
Y para poder ejecutar la función que os decía,
lo que tenemos que hacer es justamente crear la instancia.
Así que hacemos new person o persona, no me acuerdo.
Vale, persona.
Y hacemos p.get, ¿vale?
Pidamos el peso.
Vamos a darle a execute.
Y ahora, fíjate, bueno, porque he dejado,
voy a quitar este console.log que se ejecuta en evaluación, ¿vale?
Vale, vale.
Entonces, alguien decía, no le veo la utilidad.
Alguien decía, no le veo la utilidad.
Mira, ahora que ya vemos cómo funciona esto,
que fíjate que hace login, gateway, execution with arguments.
En executing, after, returning.
Bueno, esto es returning, yo no sé inglés.
75.
Esto, esto que es una tontería como un piano lo que hemos hecho,
esto ya te abre un mundo de posibilidades.
Pero un mundo de posibilidades.
Porque esto es lo que significa que puedes hacer lo que te dé a la gana
antes y después de ejecutar esto.
¿Qué quiere decir?
Quiere decir que en lugar de logger,
a este le puedes llamar tracking, por decir algo.
Y lo que podrías hacer es que tuvieras aquí un...
Además, puedes utilizar más de un decorador, obviamente.
Puedes hacer tracking.
Y con este tracking puedes trackear tantas veces como quieras
cada vez que se llame esto.
De forma totalmente declarativa.
¿Por qué?
Porque al final lo que puedes hacer, en lugar de ponerlo dentro del método
que estarían mezclando con la lógica,
tú aquí podrías llamar, sin necesidad de hacer esto,
podrías hacer aquí una llamada asíncrona, ¿vale?
Dentro de tracking podrías hacer aquí una llamada asíncrona
con lo que te ha devuelto esta llamada.
Puedes decir, ah, pues voy a hacer el tracking directamente y ya está.
¿Qué más podrías hacer?
Podrías hacer uno de tracing.
O sea, para ver cuánto tiempo está tardando en ejecutarse una función.
Por ejemplo, en lugar de tracking le podemos llamar...
Bueno, la había llamado...
A ver, si podemos ir para atrás.
Logger, ¿no?
Con el logger tú aquí podrías saber perfectamente,
sin ningún tipo de problema,
cuánto está tardando una función,
sin necesidad de poner dentro el método del consult time, ¿no?
Podrías tener consult time.
Y aquí podríamos poner name, ¿vale?
Consult time name, consult time.
Puedes hacer esto.
Y entonces ya no tienes que entrar dentro del método.
Vamos a ver si esto funciona, ¿vale?
TR, ¿dónde me he dejado el TR este?
Me he dejado este.
¿Vale?
Fuera.
¡Piu!
Vale, consult time is not a function.
Esto es un bug, porque es algún problema del playground.
Pero bueno, imagínate que esto funcionase,
porque funcionar debería funcionar.
Esto es lo que podríamos hacer ahora,
en lugar de tener que entrar en el método en el que quieres poner,
pues digas, no, es que quiero aquí poner que...
A ver cuánto tiempo tarda esta función.
Entonces irías a la función, pondrías aquí consult time, no sé qué, no sé cuánto.
Y de esta forma lo puedes hacer totalmente de gratis, ¿vale?
Sin ningún tipo de problema.
Vale, hay gente que me pregunta, vale, pero esto, ¿cómo se le puede pasar un parámetro?
Sí que se le puede pasar parámetros.
Lo que tienes que hacer para esto sería crear una decorator factory, ¿vale?
Lo que puedes hacer aquí, por ejemplo, en lugar de llamar esto así,
podríamos llamar...
Vamos a probar, a ver si esto soy capaz de hacerlo.
Console logger factory, podríamos ponerle aquí logger name, ¿vale?
Vamos a poner aquí console log, voy a poner aquí logger name, logger name,
y vamos a poner aquí call function.
Voy a probarlo y os digo, y os explico.
Call function, voy a poner el name, ¿vale?
Console log, y el logger factory tendríamos...
Voy a quitar todos los loggers estos que no utilizamos por ahora.
Luego igual les podemos echar otro vistazo.
Y luego os voy a enseñar otro ejemplo de cómo hacer un decorador de una cosa súper chula,
que es para crear web components, para que lo entendáis, ¿vale?
Y aquí lo que podríamos hacer, el logger factory, este...
Bueno, le podemos dejar el logger factory, le podemos dejar el nombre de logger directamente.
Y aquí el logger name le podemos poner métodos.
Por ejemplo, execute, vale, métodos...
Ah, vale.
Esto sería...
Function...
Vale.
Pues fíjate.
Ahora lo que puedes hacer es pasarle un parámetro.
Le estamos pasando un parámetro y lo importante...
Esto lo que estamos haciendo es un decorador...
Decorator factory.
¿Qué quiere decir esto?
Que ahora puedes tener diferentes decoradores, ¿vale?
Tú le pasas como parámetro esto, lo ejecutas aquí, y esto te crea el decorador.
Y ya está.
En esta forma podemos tener aquí logger métodos,
y podríamos poner aquí logger, por ejemplo, logger getter.
Getter, ¿vale?
Y aquí, si yo le pusiera aquí que, aparte del kind, también puede ser que sea un getter,
esto debería funcionar.
Bueno, debería recuperarlo, claro.
Debería hacer p.peso, y aquí tendríamos getter.
O sea, ya tengo como el mismo decorador que le puedo pasar un parámetro, justamente.
¿Vale?
Le puedo pasar un parámetro a mi decorador.
Y esto es súper potente, porque, claro, una vez que le pasas un parámetro,
es que imaginaos, imaginaos con APIs incluso, o para cachés.
Mira, para cachés.
Vamos a poner un ejemplo de caché.
¿Vale?
Podrías tener aquí caché, una cachéqui.
¿Vale?
Cachéqui.
Es que es muy potente el tema de los decoradores, ¿eh?
Es muy potente.
Porque, por ejemplo, aquí podríais hacer, si tenemos los métodos,
imaginad que tenemos, que no queremos meter la caché, que a veces, muchas veces tiene sentido, ¿no?
Voy a hacer la caché un poco guarra, pero solo para que lo tengáis en cuenta, ¿vale?
Voy a poner caché aquí, la voy a hacer un poco cochina.
Y kind method, ¿vale?
Vamos a poner return function, ¿vale?
Y vamos a poner cachéqui.
Vale, la cachéqui, lo que vamos a hacer aquí es caché, cachéqui.
Si tenemos caché de la cachéqui, lo que podemos hacer es devolverla, ¿vale?
Retour.
Esto es increíble.
Esto es la leche, porque esto te...
Te huele a la mente.
Porque, mira, tendríamos esto, ¿no?
Si tenemos desde la caché, cachéqui, devolvemos la caché.
Si no, lo que hacemos aquí es caché, cachéqui, que esto es una cosa muy parecida a lo que hicimos el otro día.
Retour value, y aquí lo que podemos hacer es return, return value.
Con esto, justamente con estas pocas líneas de código, hemos hecho un decorador que nos puede servir de caché.
¿Cómo lo utilizamos?
Pues nada, nos vamos aquí, ponemos caché, le decimos la cachéqui, que esto...
La cachéqui, porque yo le he puesto cachéqui, porque yo he querido.
Pero si queréis, podríais utilizar incluso el propio nombre del método.
Podríais utilizar el nombre del método.
Con el nombre del método, podríais ver cuáles son los argumentos que le llegan,
y dependiendo de esos argumentos, cachear o no cachear.
O sea, son increíbles las posibilidades que tenéis aquí.
Así que pongamos que pongo lo de cachéqui.
Y aquí digo getWay.
Entonces, lo que...
Imaginad que aquí voy a poner un console.log para saber si ha ejecutado lo de dentro, ¿vale?
Y vamos a quitar los loggers para que no nos añadan ruido.
Lo que quiero ver es que si yo ejecuto el gateway, que esto pueden ser llamadas asíncronas, llamadas APIs.
Esto lo podéis utilizar con la local storage, con la memoria, con lo que sea.
O sea, mil millones de historias.
Lo que...
La idea es que lo que veamos aquí es que por más veces que llamamos al gateway,
solo este console.log, solo se debe ejecutar una vez.
Si lo he hecho bien.
Si no, lo revisaremos.
Execute.
Vale, esto es porque yo la he liado con...
¿Con qué la he liado?
Se me ha olvidado en algún sitio o algo.
Retour, caché...
Caché, cachéqui...
Porque este es un aspecte token de dos puntos.
Esto...
Ah, coño, que hay dos cachés aquí.
Hay dos cachés, amigos, y nadie me ha dicho nada.
Es que, claro, trabajar sin linter...
Es un poco más complicado, ¿eh?
Vale...
Vale, ya está.
Caché, y aquí tenemos la caché.
Vale, return value is not defined.
Vale, return value...
Ah, ¿ves?
Y aquí se me ha equivocado también el nombre.
Vale.
Vale, pues ya está.
Mira, fíjate.
Lo que hemos hecho en un momento.
O sea, hemos hecho un método...
Un decorador con qué?
Diez, nueve...
Nueve líneas de código.
Hemos utilizado nueve líneas de código.
Y hemos creado un decorador que lo que hace es cachear cada vez que se llama este método.
Que sé que el método...
Claro, alguien dirá, ¿para qué vas a cachear esto?
Porque os conozco y seguro que lo estáis pensando.
Pero imaginad que aquí lo que tenemos aquí es una llamada asíncrona a una API.
Y podéis hacer esto.
Caché.
Y esto es el cachéqui, porque yo he puesto esto, pero podría ser lo que sea, ¿eh?
Peso, por decir algo.
O sea, puede ser lo que queramos.
Pero lo que estamos haciendo es evitar la ejecución de lo que hay dentro gracias a un decorador de nueve líneas de código.
Y lo mejor, totalmente reutilizable.
O sea, estamos haciendo el patrón decorador de forma que si tuviéramos otro, ¿no?
Get from database wave, ¿no?
Pues esto mismo podríamos volver a utilizarlo así, tan fácil como esto.
¡Plam!
Ya está.
Ya estamos reutilizando la misma caché en otro método totalmente distinto que devuelve una cosa totalmente diferente.
Y esta es la magia, justamente, de los decoradores.
La magia de poder reutilizar fácilmente este tipo de código, ¿vale?
¿Por qué los decoradores existen muchas veces?
Los decoradores existen para evitar introducir esa lógica de modificación dentro del método y ponerla desde fuera.
Y esto tiene un montón de ventajas en cuanto a mantenibilidad del código de patrones, inyección de dependencias, el patrón decorador, ¿no?
Porque lo que estás haciendo es tu método funciona exactamente igual, no tienes que tocarlo y, en cambio, lo decoras, ¿no?
Le añade funcionalidad, modifica su comportamiento desde fuera.
Y esto de mantenibilidad es que, de verdad, tiene muchísimas mejoras.
¿Qué diferencia tienen con los de TypeScript?
No me conozco todas, pero una muy importante es que no tenemos decoradores de parámetros, ¿vale?
En TypeScript existen los, por ejemplo, aquí tendríamos, pongamos que tenemos un value, ¿no?
Bueno, pues los valores, los parámetros de una función tú lo podrías decorar en TypeScript.
Esto lo puedes hacer.
Esto no funciona y no parece que vaya a funcionar en el corto plazo en JavaScript.
Y luego, además, creo que tiene alguna diferencia sobre este método de aquí.
¿Tiene alguna diferencia?
No todas, no todas.
No sé si hay algún, los kinds o los accessors, por ejemplo, hay una cosa nueva que se llama accessors, aquí, en JavaScript, que va a ser así.
Que está relacionado con decoradores, pero es otra proposal, ¿vale?
Y es diferente.
Lo que hace un accessor, lo que hace es que te crea, digamos, lo que hace, voy a intentar traducirlo más o menos,
pero sería la propiedad privada, el get, ¿vale?
Que esto lo que haría sería devolverte de la propiedad privada y el set, ¿no?
Que esto sería la propiedad privada 75.
Sería algo así, ¿vale?
O sea, esto de aquí se traduciría, pero no me hagáis mucho, mucho caso, porque tampoco me lo he podido mirar muy bien,
pero creo que es así, ¿vale?
Luego la gente se nos ve en los comentarios de YouTube, esto no es así, estás engañando a la gente.
Bueno, no me lo he podido ver con detalle todavía, ¿vale?
Porque no me ha dado tiempo, pero creo que hace algo así, creo, ¿vale?
Que esta línea de aquí hace algo como esto, ¿vale?
Vale, os voy a enseñar otro decorador, bueno, otra forma de utilizar el decorador, que también es bastante importante.
Me acaban de ratear la suscripción de tres meses, pagando con Paypal.
¿Alguien sabe cómo puedo resolverlo?
¿Cómo que ratear, Edgar?
¿Qué quiere decir eso?
Acabando el directo seré JavaScript Decorator Dev.
O Dev, o Dios, Dios Decorator.
¿Vale?
Vale, os voy a enseñar dos, para que veáis uno que a mí, personalmente, me parece que tiene bastante potencial.
Voy a intentar, no va a funcionar, lo voy a intentar hacer con un poco de pseudocódigo,
porque tendría que pensar muchas cosas, pero me parece que es bastante interesante.
Pongamos que tenemos una clase, ¿vale?
Que tenemos, yo que sé, que es para recuperar...
Vamos a llamarle cómics, por decir algo, ¿vale?
Y vamos a poner aquí un async get data.
Y es a partir...
O get super hero info, ¿vale?
Y ahí le pasáis la id.
¿Ok?
Entonces, muchas veces, de nuevo, pseudocódigo, y a lo mejor algo no funcionaría del todo, pero solo para que os hagáis la idea, ¿vale?
Api.get, o sí, get super hero info...
Tenemos aquí de la API, ¿no?
Y aquí tendríamos la respuesta.
Vamos a poner la info, la teníamos aquí.
Muchas veces, a lo mejor, lo que queréis hacer en este tipo de método, en el que es recuperar información de una API y todo esto, pues a lo mejor hay veces que queréis hacer algo antes, como cambiar el loading.
Esto es algo parecido en React, que lo habréis visto un montón de veces.
Por ejemplo, set loading.
Y aquí, pues lo ponéis a...
Pongamos true, ¿vale?
True.
Cambiar el loading.
Entonces, recuperar los datos, ¿vale?
Esto ya lo hemos hecho.
Recuperamos los datos.
Y además, esto lo hacemos con un try catch.
Pues haríamos aquí el try catch.
Así que aquí hacemos el try catch.
Y esto lo vamos a transformar.
Todo lo que estamos haciendo lo vamos a transformar más o menos en un decorador para que veáis la magia también de los decoradores y la ventaja que puede tener.
¿Vale?
Entonces, haríais todo esto.
Lo importante...
Esto es lo importante.
Lo importante es esto.
Entonces, en el try catch, pues podríamos poner aquí this send error, por ejemplo, o track error, por decir algo.
Track error y aquí le pasamos el error.
Y finalmente, claro, el this.setLoading, esto tenía que ser false.
Por poner un ejemplo.
Por poner un ejemplo.
Claro.
Esto al final, lo que podríais hacer fácilmente...
A ver, no sé si me he puesto uno de más.
No, no he puesto...
Vale, este iría aquí.
¿Vale?
Esto, imagínate esto así.
Y que tenéis otro método, otro método para recuperar, pues por ejemplo, todos los...
¿Ves?
Tengamos aquí get super...
Mira, en lugar de send loading, set network status.
¿Vale?
Porque así parece más global y va a tener más send network status.
Vamos a poner aquí idle, ¿vale?
Este es el típico ejemplo también.
Vale.
Send network status, no sé qué sé cuánto.
Imaginad que tenéis otro método aquí.
Otro método.
Pa, pa, pa, pa.
Que hace get super hero info.
Bueno, pues aquí get super heroes.
No sé si esto, esto creo que es así.
No.
Joder.
Ah, sí.
Vale.
Pero aquí es get all super heroes.
¿Vale?
Y de nuevo, lo importante es esto.
Pero necesitamos hacer todo lo demás.
¿Vale?
Necesitamos hacer todo lo demás.
Porque si no, podemos tener problemas en nuestra aplicación o lo que sea.
Pueden ser asíncronos.
Claro, claro que pueden ser asíncronos.
Sí, sí.
O sea, lo del coran, tú por dentro puedes hacer una wait, puedes hacer lo que tú quieras.
Bueno, como veis aquí tenemos como dos métodos, ¿no?
Que necesitamos hacer un montón de cosas.
Y estamos repitiendo el código dentro del método.
Pues lo que podríamos hacer es crear un handle API request.
Y aquí lo que podríamos hacer, aquí el handle API request, esto lo que tendríamos que hacer es,
podríamos recuperar.
Estoy pensando.
Handle API request, tendríamos el, vale, tendríamos el value, ¿no?
Que es lo que hemos visto antes.
Y tendríamos el name y el kind, ¿no?
Bueno, lo que podríamos hacer aquí es hacer todo esto que habíamos hecho antes.
Básicamente parecido a lo que hemos hecho aquí.
¿Vale?
Hacemos esto aquí, if kind, method, ta, ta, ta, ta.
Y lo que hacemos en este caso, hostia, es una mierda la tabulación que no funciona.
Lo que podemos hacer en este caso, pues nada, es que es todo lo mismo.
Esto lo sacamos.
¿Por qué?
Porque esto en todo lo hacemos igual, ¿no?
Si el kind method, pues lo que hacemos es que esto, hacemos esto.
Luego hacemos el, bueno, esto tiene que devolver, esto tendría que devolver una sync function.
Y esto lo haríamos dentro, ¿eh?
Esto lo haríamos aquí.
¿Vale?
Entonces haríamos el sitnet, ta, ta, ta.
Importante, ves que alguien me preguntaba, ¿puede ser async o no?
Bueno, pues aquí lo tienes, async.
Luego tendríamos esto y ya pues sería cuestión de pasar casi todo esto.
Esto obviamente tenemos que cambiarlo.
Bueno, ahora lo cambiamos.
¿Vale?
Podríamos poner aquí.
Esto lo pondríamos aquí.
Y esto que habíamos puesto aquí, esto que habíamos puesto aquí, bueno, me faltaría devolverlo, pero bueno, no pasa nada.
Podríamos ponerlo aquí al final, set, return, return.
Y aquí tendríamos el, esto lo quitaríamos de aquí.
Podríamos hacer esto.
Bueno, y esto en lugar de hacer el await API, no sé qué, pues podríamos tener aquí el original, ¿vale?
Bueno, el apply que hemos hecho antes, ¿no?
Value.call this args.
Estamos llamando exactamente el mismo, pero lo estamos llamando como await, lo estamos esperando y ya está.
Y ahora aquí este handle API request, lo único que tenemos que hacer es ponerlo aquí y todo lo que habíamos hecho antes, pues lo cambiaríamos y esto lo dejaríamos exactamente así.
Y lo bueno es que esto ahora lo ejecutaríamos aquí también y todo esto lo quitaríamos y ya lo tendríamos exactamente igual.
Y esta es la magia de decoradores, que quitando lo que es accesorio, digamos, lo estás quitando de dentro del método y lo estás poniendo fuera.
Y además lo estás haciendo reutilizable.
Y esta sería un poco la idea, ¿vale?
Hostia, me he dejado esto, pero bueno, ya me habéis entendido más o menos, ¿no?
Me habéis entendido.
El tema, esta sería la idea, ¿vale?
Lo hacemos una vez, bastante fácil.
En este caso le he puesto el kind method por revisar.
De hecho, lo que puedes hacer aquí es, si llega a este punto, throw new error decorator handle API request use in something different than method.
Imagínate que este decorador solo quieres que se puedan utilizar en los métodos.
Puedes hacer esto, puedes hacer la cláusula al revés, ¿vale?
Pero ya tendríamos esto, con una sync y justamente con lo mismo.
Bueno, en este caso le he sacado aquí el info, ¿eh?
Esto mejor si le ponemos a ti el return o value to return o value to return.
Lo devolveríamos así y esto sí que funcionaría.
Y ya estaríamos sacando esto directamente sin ningún tipo de problema y ya lo tendríamos.
¿Vale?
Nos vemos en la Canaria.js.
Recuerda el punto criollo.
Tienes que...