@tiagox
¡Hola que tal!
Soy @tiagox
Code Inquisitor
at
Ranter
at
Me quejo de (casi) todo
Implementado por las colecciones
Habilita el consumo de todos los elementos de forma progresiva
El consumo es de un elemento a la vez
Productor ⇽ Consumidor
El Consumidor tiene el control
Frente a un pedido del Consumidor el Productor puede:
Es la base de la programación orientada a eventos
Permite informar a los suscriptores sobre cambios
Publisher ⇾ Subscriber
Productor ⇾ Consumidor
En este caso es el Productor el que tiene el control
En el caso de no querer recibir más datos, el Consumidor debe explícitamente desuscribirse
Hay 2 aspectos que se dejaron de lado:
Hay 2 aspectos que se dejaron de lado:
Una solución sería, registrar 3 callbacks:
Iterator ~ Observer
Observable
Streams
Colecciones + Tiempo
Colecciones
{1, 2, 3, 4, 5, 6, 7, 8}
Puedo solicitar los datos cuando yo lo decido
Colecciones + Tiempo
{…1……2…3………………4…5…6………7………8}
Los datos me llegan asincrónicamente
… no se almacenan
… tengo que procesarlos a medida que llegan
ReactiveX
The Observer pattern done right
ReactiveX is a combination of the best ideas from the Observer pattern, the Iterator pattern, and functional programming
Si
Si
Pero, ¿qué nos importa de la Programación Funcional?
Evitar side effects
¿Cómo?
Creando Funciones Puras
¿Para qué?
A pure function is a function where the return value is only determined by its input values, without observable side effects.
Colecciones
forEach
map
filter
reduce
flatten
forEach
[1, 2, 3, 4, 5].forEach(x => {
console.log(x)
})
> 1
> 2
> 3
> 4
> 5
map
[1, 2, 3, 4, 5].map(x => x * 2)
> [2, 4, 6, 8, 10]
filter
[1, 2, 3, 4, 5].filter(x => x % 2 !== 0)
> [1, 3, 5]
flatten
[[1], [], [2, 3], [4, 5]].flatten()
> [1, 2, 3, 4, 5]
Streams
map
|---1------2---3------------4---5--->
map(x => x * 2)
|---2------4---6------------8---10-->
filter
|---1------2---3------------4---5--->
filter(x => x % 2 !== 0)
|---1----------3----------------5--->
flatten
|---1| |-------2--------------3| |------| |-----------4------5|
flatten()
|---1---2--------------3---4---5|
takeUntil
|---1------2---3-------------4---5---> |---------------------A---> otherStream
takeUntil(otherStream)
|---1------2---3------|
Todo muy lindo, pero…
Hay que modelarlo
Todo es un stream
Rx.Observable.create(observer => {
// …
observer.onNext(data)
// …
observer.onError(error)
// …
observer.onCompleted()
})
Rx.Observable.create(observer => {
let counter = 0
const interval = setInterval(() => {
if (counter < 10) {
observer.onNext(counter)
counter++
} else {
clearInterval(interval)
observer.onCompleted()
}
}, 1000)
})
Rx.Observable.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Rx.Observable.fromPromise(fetch(requestUrl))
Rx.Observable.fromEvent(saveButton, 'click')
getElementDrags = (element) =>
element.mouseDowns
.map(mouseDown =>
document.mouseMoves.takeUntil(document.mouseUps))
.flatten()
getElementDrags(image).forEach(position => {
image.position = position
})
element.mouseDowns
|---MD-------------------------------------------------------->
document.mouseMoves
|------MM---MM---MM------MM------MM---MM---MM---MM------MM---->
document.mouseUps
|-----------------------------------------MU------------------>
mouseDowns.map(`take mouseMoves until mouseUp`)
|------------------------------------------------------------->
+---MM---MM---MM------MM------MM---MM-| ← Meta Stream
flatten()
|-------MM---MM---MM------MM------MM---MM--------------------->
searchResultSets = keyPresses
.throttle(250)
.map(key =>
getJSON('/search?q=' + input.value)
.takeUntil(keyPresses))
.flatten()
searchResultSets.forEach(
result => { updateSearchResults(result) }
error => { showError('Server down') }
})
~ fin ~