Video Summary and Transcription
Esta Charla introduce el concepto de utilizar proxies en JavaScript para la gestión del estado. Explora la implementación de proxies, observando propiedades y creando cachés, construyendo el proxy y observando cambios con proxies. La Charla también discute el uso de la biblioteca Taits para la gestión del estado y las implicaciones de rendimiento de los proxies. Se comparan TypeScript y JavaScript, y se comparten los resultados de una encuesta sobre su uso.
1. Introducción a los Proxies
Hola, soy Will Johnston, un defensor del desarrollador en el equipo de DevRel de WP Engine. Hoy, hablaré sobre cómo usar proxies o la API de Proxy de JavaScript para la gestión de estado.
Hola, soy Will Johnston. Soy un defensor del desarrollador en el equipo de DevRel de WP Engine, y hoy estoy aquí para hablarles sobre cómo podrían usar proxies o la API de Proxy de JavaScript para la gestión de estado. Los proxies, si no están familiarizados, son una forma de observar algunas de las operaciones subyacentes en objetos dentro de JavaScript. Entonces, si están familiarizados con object.observe, que ya no existe, pero que fue el precursor de los proxies. Y si también están familiarizados con los descriptores de propiedades o object.defineProperty, eso es algo similar a los proxies. Los proxies simplemente habilitan un poco más de funcionalidades completas.
2. Introduction to Proxies (continued)
He estado escribiendo código desde que tenía unos 10 años. Me interesé en los proxies para entender qué está sucediendo debajo. Los métodos de proxy como get y set traps son simples y fáciles de entender. Reflect se utiliza para redirigir las operaciones al objeto original y evitar problemas de herencia. Creemos una demostración básica utilizando un proxy para observar los cambios en un objeto. Interceptamos las operaciones get y set y las registramos. Podemos usar el proxy como un objeto normal.
Un poco sobre mí. He estado escribiendo código desde que tenía unos 10 años. En la escuela secundaria, conseguí un trabajo haciendo programación web con Python, y realmente me enamoré del software en ese momento y del desarrollo de software, y desde entonces he sido un aprendiz constante. Pasé la mayor parte de mi carrera trabajando en la web y en el backend, y en los últimos años, probablemente seis u ocho años, he estado trabajando principalmente con Node en el ecosistema de JavaScript y TypeScript.
Así que realmente me interesé en los proxies porque he hecho una cantidad considerable de código .NET y C Sharp, y en C Sharp, tienes un concepto de getters y setters en un objeto, y te permite inspeccionar sigilosamente diferentes operaciones en ese objeto, y los proxies funcionan de manera similar pero para JavaScript. Así que me interesé mucho en los proxies para tratar de entender cómo puedo hacer que eso funcione porque realmente me encanta cuando puedes usar objetos como lo harías normalmente, pero por debajo, puedes entender exactamente qué está sucediendo.
Entonces, hay muchos métodos de proxy, y los métodos de proxy se utilizan para configurar trampas, por lo que puedes observar algunas de las capacidades inherentes de JavaScript para realizar diferentes funciones, eso es lo que es una trampa. Hoy vamos a usar los métodos get y set porque son simples y fáciles de entender, y no estoy tratando de profundizar demasiado con el poco tiempo que tenemos.
Algo que debes saber cuando estás usando un proxy es que realmente también necesitas usar reflect, por lo que el objeto reflect se utiliza para redirigir todas las operaciones al objeto original, por lo que si piensas en el proxy como algo que está al frente y estás escuchando el método set, cuando alguien intenta establecer, quieres usar el objeto reflect para finalmente redirigir esa operación y establecer el valor en ese objeto. La razón por la que haces esto está relacionada con evitar problemas de herencia, por lo que si creas un proxy y luego intentas heredar de él y no usas reflect, obtendrás una funcionalidad extraña donde en realidad estás cambiando el objeto original, no el objeto heredado.
Entonces, comencemos con una demostración básica, creemos un objeto de estado usando un proxy para observar los cambios en ese objeto. Crearemos un controlador de proxy, es la forma más fácil, sé que eventualmente tendré que crear un nuevo objeto, un nuevo proxy, y crearemos un objeto y nuestro controlador será nuestro controlador de proxy, por lo que sabemos que nuestro controlador de proxy será un tipo de controlador de proxy y ahí es donde tenemos nuestros métodos get y set, así que creemos esos ahora, propiedad objetivo y establecer valor de propiedad objetivo. El método get simplemente devuelve el objetivo, la propiedad en un cierto objetivo y el método set establece el valor de una propiedad en un objetivo, así que aquí diremos obteniendo valor de propiedad valor, y aquí diremos estableciendo propiedad, oops y usaremos la API reflect y así es como podemos, simplemente imita la API de proxy directamente y nos permite no tener que preocuparnos por lo que realmente sucede debajo, solo queremos inspeccionar donde nos importa y observar el cambio. Hay una pieza adicional que nos importa aquí y se llama el receptor y queremos agregarlo aquí. El receptor proporcionará al objeto reflect ese contexto adecuado. Aquí tenemos nuestro get, nuestro set, simplemente interceptamos estas operaciones y las registramos, bastante simple.
Para esto, creemos en nuestro estado, una persona, diremos primer nombre, Will. Y agreguemos también un apellido. Johnston, bien. Y luego, para ver realmente qué está sucediendo aquí, tendremos que console.log, state.person.firstname. Entonces, lo que esperamos aquí es que registre, ya sabes, obteniendo persona aquí. Podrías esperar que también registre obteniendo primer nombre. Veremos si lo hace en un segundo. Spoiler alert, no lo hace. Y solo voy a decir aquí, y lo llamaré William. Intentaremos establecer el primer nombre y eso está bien. Bien. Ten en cuenta que cuando creamos este proxy, podemos usar state como un objeto normal. No tenemos que preocuparnos. Entonces, si tienes, normalmente usarás una biblioteca que podría estar utilizando un proxy en el fondo.
3. Observando Propiedades y Creando Cachés
Obtienes un objeto que usas como un simple objeto de JavaScript. Y eso es lo que es realmente agradable de los proxies, es muy sigiloso. Para observar recursivamente todas las propiedades de este objeto, necesitamos realizar un seguimiento de las propiedades y la ruta desde el objetivo original. También necesitamos realizar un seguimiento de si ya hemos establecido un proxy en un objeto. Creemos una caché de ruta y una caché de proxy. En un escenario del mundo real, tendríamos que hacer comprobaciones en el valor para evitar crear un proxy en un objeto primitivo. Si el valor no es una cadena, obtenemos la ruta y la aumentamos.
Obtienes un objeto que usas como un simple objeto de JavaScript. Y eso es lo que es realmente agradable de los proxies, es muy sigiloso.
Veamos qué hace esto aquí. Node... Oh, el receptor no está definido. Agreguemos el receptor aquí. Bien. ObteniendoPersona estableciendoPersona. Así que no hay obteniendoPersona aquí. No dijo obteniendoPersona, y no dijo obteniendoPrimerNombre, y luego aquí establecemosPersona. No dijo estableciendoPrimerNombre, y no dijo estableciendoApellido.
Para hacer eso, tendríamos que tener una forma de observar recursivamente todas las propiedades de este objeto. Veamos qué implica eso aquí. Para hacer eso, necesitaríamos realizar un seguimiento de todas las diferentes propiedades y realmente de la ruta desde el objetivo original hasta esas propiedades. La otra cosa que necesitaremos realizar un seguimiento es si ya hemos establecido un proxy en un objeto, porque si intentas crear un proxy en algo que ya es un proxy, obtendrás un error, y no queremos lidiar con eso. Necesitamos crear un par de cachés.
Creemos una caché de ruta. Usaremos un mapa débil. Y una caché de proxy. También usaremos un mapa débil. Aquí está bien. Primero, obtengamos el valor. Ahora, en un escenario del mundo real, tendríamos que hacer muchas comprobaciones en este valor porque no quieres terminar creando un proxy en un objeto primitivo, como cadenas, números, booleanos, etc. Pero para este demo, simplemente comprobaremos si el tipo de valor es una cadena. Si es una cadena, simplemente devolvemos el valor y listo. Si no es una cadena, necesitamos obtener la ruta. Entonces, si este objetivo ya está en nuestra ruta, que debería estar, obtendremos la ruta aquí, y luego necesitamos aumentar la ruta. Primero diremos, si la ruta está vacía, si este es el objetivo original de nivel superior, no tendrá ruta.
4. Building the Proxy
Si la ruta está vacía, agregamos un punto. Creamos una función para construir nuestro proxy, pasando el valor, la ruta y la propiedad. Nos enfocamos en la trampa de obtención para observar el acceso a la propiedad. Verificamos si ya existe un proxy en la caché. Si no es así, creamos un nuevo proxy utilizando el controlador de proxy recursivo. Agregamos el proxy a la caché y lo devolvemos.
Entonces, si la ruta está vacía, agreguemos un punto. Esto es, ya sabes, esto es solo notación de punto, así que terminaremos con una ruta con notación de punto. Y luego crearemos una función que construirá nuestro proxy, pasaremos el valor, y pasaremos la ruta y la propiedad. Así que eso nos permitirá construir nuestro proxy.
No me preocuparé por el set para los propósitos de esta demostración, porque es mucho más complicado. Pero solo nos preocupemos por el get, para poder observar cuando intentamos obtener una propiedad. Así que construyamos esta función de construcción de proxy, build proxy. Y toma, sí, valor y propiedad. Nuestra propiedad va a ser esa ruta. El valor va a ser el objetivo en el que queremos crear el proxy. Lo primero que haremos es establecer en la caché de ruta para que aquí arriba podamos buscar todas las rutas. Así que siempre sabremos la ruta y podremos construir recursivamente esta ruta y esta caché de rutas. Y primero vamos a usar este objetivo para verificar si ya tenemos un proxy. Así que queremos buscar en la caché de proxy este valor. Y si existe, entonces no necesitamos hacer nada. Así que diremos, si no hay proxy, simplemente verificaremos si queremos o realmente seamos más explícitos. Si el proxy es indefinido, primero, intentemos crear el nuevo proxy. Vamos a usar el mismo controlador de proxy que es nuestro controlador de proxy recursivo. No nos preocupemos por registrar nada en la caché. Y luego tenemos este proxy.
Necesitamos agregarlo a la caché de proxy. Entonces, proxy cache.set(value, proxy). Ahí lo tenemos. Ahora hemos definido que estamos haciendo un seguimiento de esta caché de proxy. Así que va a tener todos nuestros proxies. No sobrescribiremos accidentalmente un proxy con otro proxy. Tenemos este try catch, en caso de que algo salga mal. Bien, hemos construido nuestro proxy. Tenemos nuestro getter que llama recursivamente a build proxy. Al final, build proxy devuelve el proxy, que será el valor real.
5. Observando Cambios con Proxy
Construimos un proxy para observar los cambios en un objeto. El getter recursivo nos permite observar a todos sus hijos. Pudimos observar el estado, la persona y el nombre. La recursión se detiene en el nombre porque es una cadena de texto.
Pero lo que necesitamos hacer aquí en lugar de nuevo proxy, es decir, construir proxy. Y por ahora, simplemente inicialicémoslo con un objeto vacío. Y luego diremos que state.person es igual a nombre, apellido, y sí, esto funciona. Bien, vamos a construir nuestro proxy aquí para empezar. Luego vamos a decir state.person es igual a nombre, apellido. Esperaremos que algo se registre aquí, y luego vamos a establecer la persona de nuevo y algo se registrará de nuevo. Así que tenemos persona, está aquí. Y luego tenemos nombre. Así que obtener el nombre, esto es genial. Tenemos este getter recursivo. Así que cada vez que obtenemos una nueva propiedad, construye un proxy con esa propiedad para que podamos observar a todos sus hijos. Y así pudimos observar primero el estado. Luego pudimos observar a la persona. Luego pudimos observar el nombre. Y se detuvo en el nombre porque el nombre es una cadena de texto. Así que si tuviéramos algo más aparte del nombre, eso no funcionaría para nosotros.
6. Using Taits Library for State Management
Veamos una biblioteca llamada taits, una pequeña biblioteca para la gestión del estado utilizando la API de proxy. Usaremos Taits para obtener publicaciones de un sitio de WordPress sin cabeza utilizando Apollo y GraphQL. Nos suscribiremos a las publicaciones y registraremos la longitud cuando se establezca el objeto de publicaciones. También observaremos las 10 publicaciones en un bucle y recuperaremos el título de cada publicación. Por último, crearemos una función para obtener las publicaciones.
Veamos una biblioteca que escribí llamada taits. Taits es una pequeña biblioteca para la gestión del estado que utiliza la API de proxy de manera similar a cómo la estamos utilizando aquí, pero te permite simplemente crear tu proxy, hace todo lo que necesita, y luego puedes suscribirte a cambios en rutas de ese proxy.
Así que lo eliminaré. Ya he instalado todas las dependencias que necesito, pero lo que vamos a hacer es usar Tait, y obtener publicaciones de un sitio de WordPress sin cabeza. Así que usaremos Apollo. Tenemos un sitio de WordPress sin cabeza configurado con GraphQL, y simplemente vamos a obtener las publicaciones. Voy a copiar y pegar algunas cosas aquí para no escribirlo mal, pero vamos a usar Apollo y hacer una llamada a GraphQL para obtener las publicaciones de nuestro sitio de WordPress sin cabeza. Y luego estableceremos esas publicaciones en el estado e intentaremos observar los cambios.
Lo primero que haces con Taits es obtener un objeto de estado y un método de suscripción. Y si te preguntas por qué lo llamo Taits, no soy muy original, Taits es simplemente estado con una S al final. Así que vamos a suscribirnos a las publicaciones. Queremos saber cuándo se establece el objeto de publicaciones y esperamos que las publicaciones sean un array de publicaciones. Así que digamos, si no es array.isArrayPosts no hagas nada. Solo nos importa si tenemos publicaciones. Y luego registremos, hay posts.lengthsPosts. De acuerdo. Así que cuando establezcamos las publicaciones en el estado, se registrará la longitud de las publicaciones. Por defecto, WP GraphQL descarga 10 publicaciones y soy consciente de que el sitio al que vamos a llamar llama a 10 publicaciones. Así que llevemos esto un paso más allá y observemos en un bucle las 10 publicaciones. Por adelantado, observa que nuestro estado no tiene nada, no hemos definido publicaciones ni nada en nuestro estado, pero podemos observar cambios de antemano. Así que suscribámonos en un bucle e intentemos obtener el título de cada publicación. Entonces, si no hay título, devuelve. Para hacer esto, queremos este bucle for y luego queremos posts.title. Taits puede convertir esto en un mapa y entender que necesitamos escuchar, ya sabes, publicación como un array. Queremos escuchar la propiedad cero a nueve en ese array, o el índice cero a nueve. De acuerdo, ahora creemos nuestra función para obtener las publicaciones. Y simplemente voy a copiar algo de esto aquí para que lo haga bien. Sí, hagamos eso. Obtener publicaciones. Porque de lo contrario no lo haré bien.
7. Importando Tates y Observando Cambios en el Estado
Si hay errores, simplemente los registraremos. Tengo un sitio de WordPress configurado y listo para obtener publicaciones utilizando la API de WPGraphQL. Hacemos una consulta para obtener los títulos de los nodos de las publicaciones y establecemos el resultado en 'posts'. Después de llamar a 'get posts', importamos exitosamente Tates en un escenario del mundo real, actualizando el estado y notificando a los suscriptores. Puedes encontrar el código en mi GitHub y seguirme en Twitter para cualquier pregunta. Gracias, Will, por la charla. Veamos la encuesta.
Entonces, si hay errores, simplemente los registraremos.
De acuerdo, tengo un sitio de WordPress configurado en esta URL. Voy a usar 'isomorphic fetch' porque estamos usando Node aquí. Y mi sitio de WordPress ya tiene una lista de publicaciones, así que está listo para funcionar, listo para obtener publicaciones. Y vamos a copiar la consulta aquí. 'Client.query'. Entonces, estamos haciendo una consulta jql aquí para obtener los títulos de los nodos de las publicaciones. Esto es solo la API de WPGraphQL. Y luego estableceremos 'post' en 'result', o 'request result'.data.Posts.nodes. Así que suponiendo que podamos hacer esta solicitud, obtener la publicación, estableceremos el array, que son estos nodos, y cada nodo tiene un título, en 'posts'. Muy bien, y lo último que tenemos que hacer aquí es llamar a 'get posts'. Entonces veamos, ejecutemos esto y veamos qué nos da. No nos da nada, genial. ¿Qué hicimos mal? Volvamos atrás aquí. Escribí mucho código sin hacer mucho aquí. Entonces, ¿qué hemos hecho? Ah, necesitamos un 'await'. Ahí lo tenemos. Con nuestro 'await', realmente esperó a que la publicación regresara y luego tenemos, hay 10 publicaciones y por cada publicación, estamos registrando el título. Mis títulos son muy originales, publicación 41, 40, hasta 32. Y ahí lo tienes. Hemos importado exitosamente Tates en un escenario más parecido al mundo real. Estamos llamando a data, estamos obteniendo publicaciones de Headless WordPress y estamos estableciendo el estado y se está actualizando para nosotros y nuestros suscriptores. Lo que me gusta de esto es que no tenemos métodos específicamente para establecer. Simplemente establecemos 'posts' directamente aquí y todos nuestros suscriptores se actualizan. Así que no tienes que preocuparte por eso.
Si te gustó esta charla, puedes obtener todo el código en GitHub. Si vas a github.com/wjohnstow, ese es mi GitHub y lo tengo alojado allí. Puedes seguirme en Twitter en wjohnstow y habrá una pequeña sesión de preguntas y respuestas para que pueda responder cualquier pregunta que tengas allí también. Gracias, Will, por esta excelente charla. Ahora veamos la encuesta.
8. TypeScript vs JavaScript
TypeScript ganó con un 56% y JavaScript con un 44%. TypeScript comenzó con ventaja, pero JavaScript se puso al día. Es posible que TypeScript nunca reemplace por completo a JavaScript, ya que a algunas personas les gusta la naturaleza dinámica de JavaScript. Sin embargo, TypeScript es beneficioso para construir aplicaciones grandes.
¿Qué prefieres? TypeScript o JavaScript? Así que TypeScript con un 56% y JavaScript con un 44%. Esto es bastante interesante. ¿Te sorprende, Will? Sí, de hecho, TypeScript comenzó con una gran ventaja y luego JavaScript se acercó. Creo que, obviamente, TypeScript ganó fácilmente aquí, pero como alguien mencionó en el chat, lo consideran una derrota porque TypeScript no ganó con un 90% frente al 10%, con lo que tiendo a estar de acuerdo. Eso es gracioso. En interés completo, voté por TypeScript, así que estaba tratando de moverme un poco desde aquí. En interés completo, voté por JavaScript. Así que nos anulamos mutuamente, bien. Sí, nos anulamos mutuamente. Pero ¿crees, por ejemplo, que tal vez TypeScript pueda reemplazar a JavaScript? Entonces, creo que TypeScript probablemente nunca reemplace por completo a JavaScript porque hay personas a las que simplemente les encanta JavaScript y les encanta la naturaleza dinámica, y, bueno, más poder para ellos. Creo que cuando construyo aplicaciones grandes, veo el beneficio real de TypeScript, pero a veces, si solo estoy escribiendo pequeños scripts, JavaScript es suficiente. Sí, sí, estoy de acuerdo contigo. No creo que TypeScript pueda reemplazar a JavaScript en un futuro cercano, pero es enorme, y creo que seguirá aumentando y ganando más adopción, pero JavaScript siempre será el número uno, el líder.
Implicaciones de rendimiento de los proxies
El rendimiento de los proxies a menudo es una preocupación, pero depende del caso de uso. Si estás tratando de optimizar el rendimiento, es posible que desees evitar los proxies. Sin embargo, para un uso normal, los proxies deberían ser lo suficientemente rápidos. Existe otra biblioteca de gestión de estado llamada MobX que también utiliza proxies.
Bien, ahora, ahora pasemos a las preguntas y respuestas. Si tienes preguntas. Entonces, la primera pregunta es, ¿cuáles son las implicaciones de rendimiento de los proxies? Sí, muchas personas mencionan, al hablar de proxies, que el rendimiento de los proxies es lento en comparación con el JavaScript normal. A eso diría que realmente depende de lo que estés haciendo, pero si estás trabajando y considerando algo como reemplazar todas tus promesas con devoluciones de llamada o algo de esa naturaleza, porque estás tratando de obtener ese extra de performance, entonces tal vez deberías evitar los proxies. Pero los proxies deberían ser lo suficientemente rápidos para un uso normal. Y alguien lo mencionó en el chat, pero también hay otra biblioteca de gestión de estado llamada MobX, Mobix, no sé cómo la gente lo pronuncia, pero también utiliza proxies internamente. Sí, no afecta mucho al performance. Bien, la siguiente pregunta es de Oli. Y si alguien tiene preguntas, por favor, ve a la sección de preguntas y respuestas de la comunidad y haz preguntas a Will. Entonces, la siguiente pregunta es, me parece que Tate hace algo similar a MobX. ¿Puedes señalar las diferencias? Sí, son muy similares. Diría que MobX es una biblioteca de gestión de estado más completa. La razón por la que escribí Tate fue para algunos proyectos en los que estaba trabajando donde quería tener algún nivel de gestión de estado que fuera más que simplemente usar el contexto y el estado de React. Y no quería llegar al punto de usar MobX y aprender todo sobre eso. Solo quería un envoltorio muy simple alrededor de los proxies para poder obtener algunos datos y manejar realmente las cosas en una ubicación más centralizada. - OK. Gracias. Gracias por tu respuesta. Parece que no tenemos más preguntas. Pero si tienes preguntas, por favor avísanos. Puedes contactar directamente a Will en el canal de Discord. Supongo que también está en Twitter. Oh, hay otra pregunta. ¿Podrías compartir el enlace de GitHub para el código? Sí. Aquí está el enlace de GitHub donde puedes seguirlo. Y este es el código de la charla. Y allí encontrarás enlaces a Tate y todas esas cosas también. OK. Genial. Muchas gracias. Esta charla fue genial. Y las preguntas también. Así que gracias. Adiós. Adiós.
Comments