@composi/runtime:
Suscripciones
Efectos al Iniciarse
Cuando cubrimos init
, se explicó cómo se podía ejecutar un efecto al iniciar un programa tan solo por pasarlo como un segundo valor en la tupla que devuelve init
. En general, los efectos que se ejecutan en el inicio se conocen como suscripciones. Podemos ser más explícito sobre la implementación de una suscripción utilizando el método subscriptions
en un programa. Esto debe devolver el efecto que ejecutar.
Las suscripciones sirven para detectar los movimientos del ratón, el pulsar del teclado, los cambios de la locación del navegador o para iniciar bucles.
function empezarContar() {
let cuenta = 0
const id = setInterval(() => {
if (cuenta === 10) clearInterval(id)
cuenta += 1
programa.send(cuenta)
}, 1000)
}
const programa = {
init() {
return estado
},
view(estado, send) {
return render(La cuenta es: {estado}.
, document.body)
},
update(estado, mensaje, send) {
if (mensaje) {
// Fija el estado del programa con el valor del mensaje:
return mensaje
}
},
subscriptions(send, getState) {
return empezarContar(send, getState)
}
}
No hay nada de magia aquí. Las suscripciones hacen lo que dice la etiqueta. Usar suscripciones para ejecutar efectos al inicio
es más explícito. Pero puedes usar cualquier método, init o subscriptions, para ejecutar efectos al inicio. Subscriptions reciben las funciones send
y update
desde una suscripción mediante estas funciones.
Tanto send
como getState
son opcionales. Si no vas a acceder al estado dentro de una suscripción, no hay que proveer getState
como argumento. Si una suscripción no va enviar un mensaje, no se necesita el argument send
:
const program = {
init() {
},
view(estado, send) {
},
update(estado, mensaje, send) {
},
// getState y send son opcionales aquí:
subscriptions(send, getState) {
}
}
Atención: Las suscripciones no son para manipular el estado. El acto de cambiar el estado en un efecto resultará en que la vista y el estado estarán desincronizados. Si has producido algunos dataos en una suscripción y quieres actualizar el estado con ellos, hazlo por enviar un mensaje a una acción. Haciendo esto logrará que el algoritmo de reconciliación se ejecute, lo cual puede causar que la vista vuelva a rendirse.
Suscripciones Combinadas
Al igual que con cualquier otros efectos, puedes usar batch
para ejecutar múltiples efectos al mismo tiempo. Consulte la documentación de efectos para ver cómo hacer esto.
Ahora bien, vamos a ver cómo usar suscripciones en tanda, o más bien, combinados. Vamos a tomar dos efectos, uno para conseguir datos y otro para iniciar un evento para escuchar la pulsación de teclas. Queremos que estos do se executen cuando el programa se inicia. Puesto que se trata de dos efectos, en vez de ponerlos directamente in el método subscriptions
del program, los vamos a mantener aparte y usar una versión combinada. Puesto que vamos a conseguir los datos después de que el programa se inicie, no habrá estado para la rendición inicial del la vista. Así pues, tenemos que chequear si el estado es veraz o falso antes de retornar la rendición de la vista. Por eso, vamos a designar el estatdo inicial in el método init
cómo null
.
// Crear una unión etiquetada para el mensaje:
const Msg = union('usarLosDatosRecibidos')
// Aquí hay dos efectos.
// Cada efecto espera la función `send` como su argumento.
// Ésta será proveída automáticamente cuando los efectos en tanda se procesan.
// Efecto para consequir datos:
function fetchState(send, getState) {
(async () => {
const response = await fetch('/src/js/state.json')
const data = await response.json()
send(Msg.usarLosDatosRecibidos(data))
})()
}
// Efecto para manejar la compresión de la tecla Enter:
function handleEnter(send, getState) {
document.addEventListener('keypress', e => {
if (e.keyCode === 13) {
send(Msg.addItem())
}
})
}
// Combinar los efectos en uno:
const batchedSubscriptions = batch(fetchState, handleEnter)
// Definir el program que usar:
const program = {
init() {
// Aquí designamos el estado como null:
return null
},
view(state, send) {
// Aquí chequeamos si el estado es veraz o no:
return state && render(
, 'section')
},
update(state, msg, send) {
const prevState = clone(state)
return actions(prevState, msg)
},
subscriptions(send, getState) {
// Aquí retornamos los efectos combinados.
// No tenemos que invocar esto, solo lo retornamos.
return batchedSubscriptions(send, getState)
}
}
Abreviatura Para Suscriptions
Puedes usar el término subs
en vez de subscriptions
. Es más corto:
const programa = {
init() {
return estado
},
view(estado, send) {
return render(La cuenta es: {estado}.
, document.body)
},
update(estado, mensaje, send) {
if (mensaje) {
// Fija el estado del programa con el valor del mensaje:
return mensaje
}
},
subs(send, getState) {
return empezarContar(send, getState)
}
}