Saltar al contenido principal
Versión: v2 ⚡

El operador lazy state

El operador lazy state​

Funcionalidad experimental

El operador lazy state llegó a OpenFn en abril de 2024. Todavía se considera una funcionalidad experimental, pero funciona muy bien, ¡y te animamos a usarlo!

Si tienes comentarios, problemas o sugerencias sobre el operador lazy state, ¡nos encantaría saber de ti en la comunidad! También puedes abrir un issue en GitHub.

El operador lazy state es una sintaxis abreviada que facilita leer el state cuando pasas datos a una operación.

En lugar de escribir state.data para acceder a algo del state, puedes usar $, así:

get($.data.url);

El $ garantiza que el valor que se pasa a la operación se resuelva en el momento correcto. Piensa en ello como pasar una ruta a una parte del state, en lugar de pasar el valor de esa ruta.

Lo bueno es que básicamente puedes ignorar por completo la sección anterior y no pensar demasiado en cuándo se evalúa el state. Solo lee de $ como si fuera tu objeto state, y el runtime de OpenFn resolverá el valor correctamente en el momento de la ejecución.

El símbolo $ es en realidad solo azúcar sintáctico para (state) => state (en la mayoría de los casos, solo hacemos un reemplazo de texto al compilar tu código). Estas dos sentencias se comportan exactamente igual:

get($.data.url);
get((state) => state.data.url);

Lo llamamos "lazy state" (state diferido) porque el motor del runtime resuelve la referencia justo antes de usarla. Así se evitan muchos de los problemas de asincronía de JavaScript que se explican en Leer el state de forma diferida.

$ solo funciona dentro de las operaciones

$ solo funciona dentro de una expresión que se pasa a una operación. Dicho de otro modo, solo puedes usarlo donde podrías escribir (state) => state en su lugar (como en el ejemplo anterior).

Ejemplos de uso​

Los siguientes fragmentos de código muestran algunas formas de usar el operador lazy state. Cada ejemplo se puede reescribir sin $, pero con él la sintaxis es más corta, más legible y más expresiva.

El uso básico es simplemente pasar el state a una operación:

upsert('patient', $.data.patients[0]);

Puedes usarlo dentro de un objeto (siempre que ese objeto se pase a una operación):

create('agent', {
name: $.patient.name,
country: $.patient.country,
});

Puedes usarlo dentro de una plantilla de string:

get(`/patients/${$.patient.id}`);

O dentro de otras expresiones, como una concatenación:

create({
name: $.patients[0].first_name + ' ' + $.patients[0].last_name,
});

O en operaciones matemáticas:

create({
profit: $.report.revenue - $.report.expenses,
});

Puedes usarlo al mapear estructuras de datos:

create('user', {
countryCode: countries[$.location.country],
});

Y puedes usarlo en operaciones anidadas, como con each():

each($.data.patients,
post(`patients/${$.data.patient.id}`, $.data.patient)
);

$ no es state​

El operador $ no es un alias de state.

No se puede usar en lugar de la variable state. No se le puede asignar un valor ni puede estar en el lado izquierdo de una asignación, y solo se puede usar dentro de un argumento de una función.

Esto también significa que el operador lazy state solo sirve para LEER el state. No se puede usar para asignar valores directamente al state.

Todos estos ejemplos son errores:

❌ const url = $.data.url;
get(url);

❌ get(() => $.data.url);

❌ $.data.x = fn();

❌ fn(state => {
$.data.x = 10;
});
Reglas de compilación para usuarios avanzados

¿Cómo funciona el operador lazy state? La "magia" está en el compilador.

En pocas palabras, cada vez que el compilador ve $ en tu código, lo reemplaza por (state) => state. Así:

get($.data.url) // compiles to get((state) => state.data.url)

En la práctica, las reglas son un poco más complicadas. Cuando ve un operador $, el compilador primero comprueba que $ no se haya declarado como variable o parámetro. Si se declaró, lo ignora por completo.

Pero si considera que $ es un operador de state, el compilador primero reemplaza el símbolo $ por state, luego busca la operación a la que se está llamando y, por último, envuelve el argumento en una función flecha (si todavía no lo está).

get({ url: $.data.url }) // compiles to get((state) => { url: state.data.url })

Este "hoisting" de la función flecha permite usar expresiones más complejas e interesantes con lazy state, como plantillas de string o búsquedas dinámicas en objetos.

Si tienes curiosidad (o necesitas resolver algún problema), puedes usar el comando openfn compile de la CLI para ver el código compilado, que te mostrará cómo trata el compilador tus operadores de state.