Skip to content

Instantly share code, notes, and snippets.

@ronag

ronag/list.js Secret

Last active March 1, 2016 09:39
Show Gist options
  • Select an option

  • Save ronag/9f9fdfb7c6169e6850c4 to your computer and use it in GitHub Desktop.

Select an option

Save ronag/9f9fdfb7c6169e6850c4 to your computer and use it in GitHub Desktop.
function List(sources) {
const click$ = new Subject()
const actions = intent({ ...sources, click$ })
const state$ = model(actions).shareReplay(1)
const items$ = state$
.pluck('items')
::resolveMap(id => Asset({
...sources,
props$: state$
.pluck('selected')
.map(selected => selected.includes(id))
.distinctUntilChanged()
.map(selected => ({ id, selected })),
}))
.shareReplay(1)
return {
DOM: view({
state$,
items$: items$::resolveCombineLatest(item => item.DOM)
}),
HTTP: items$::resolveMerge(item => item.HTTP)
}::using(
() => items$::resolveMerge(item => item.click$).subscribe(click$)
)
}
export function using(...factories) {
return {
...this,
DOM: Observable.using(() => new CompositeDisposable(factories.map(f => f())), () => this.DOM),
}
}
export function resolveMap(resolver) {
const cache = new Map()
return this
.startWith([])
.pairwise()
.map(([prev, curr]) => {
const added = _.difference(curr, prev)
const removed = _.difference(prev, curr)
added.forEach(item => cache.set(item, resolver(item)))
removed.forEach(item => cache.delete(item))
return curr.map(item => cache.get(item))
})
}
export function resolveMerge(resolver) {
const pairs$ = this
.startWith([])
.pairwise()
.share()
const add$ = pairs$.flatMap(([prev, curr]) => _.difference(curr, prev))
const remove$ = pairs$.flatMap(([prev, curr]) => _.difference(prev, curr))
return add$.flatMap(item => resolver(item).takeUntil(remove$.filter(remove => remove === item)))
}
export function resolveCombineLatest(resolver, combiner = (...items) => items) {
return Observable.using(
() => {
const cache = new Map()
cache.dispose = () => cache.forEach(({ subscription }) => subscription.dispose())
return cache
},
cache => this
.startWith([])
.pairwise()
.map(([prev, curr]) => {
const added = _.difference(curr, prev)
const removed = _.difference(prev, curr)
added.forEach(item => {
const subject = new ReplaySubject(1)
cache.set(item, {
value$: subject,
subscription: resolver(item).subscribe(subject),
})
})
removed.forEach(item => {
const { subscription } = cache.get(item)
subscription.dispose()
cache.delete(item)
})
return curr.map(item => cache.get(item).value$)
})
.flatMapLatest(xs => xs.length
&& Observable.combineLatest(...xs, combiner)
|| Observable.of(combiner())
)
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment