Created
April 7, 2015 10:40
-
-
Save nmn/97440d0cdf08f6b5a2d2 to your computer and use it in GitHub Desktop.
Observe API with JS-CSP Mults
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { Component } from 'react' | |
import {operations, chan, go, take, CLOSED} from 'js-csp' | |
const {mult} = operations | |
export default function polyfillObserve(ComposedComponent, observe) { | |
observe = observe || ComposedComponent.observe | |
if(!observe){ | |
return ComposedComponent | |
} | |
const Enhancer = class extends Component { | |
constructor(props, context) { | |
super(props, context) | |
this.channels = {} | |
this.mults = {} | |
this.state = { data: {} } | |
this.resubscribe(props, context) | |
} | |
componentWillReceiveProps(props, context) { | |
this.resubscribe(props, context) | |
} | |
componentWillUnmount() { | |
this.unsubscribe() | |
} | |
setUpSubscription(key, ch){ | |
const that = this | |
go(function*(){ | |
while(true){ | |
let value = yield take(ch) | |
if(value === CLOSED){ | |
return | |
} | |
that.setState({[key]: value}) | |
} | |
}) | |
} | |
resubscribe(props, context) { | |
const newMults = observe(props, context) | |
const commonChannels = Object.keys(newMults).filter(key => !!this.channels[key]) | |
const addedChannels = Object.keys(newMults).filter(key => !this.channels[key]) | |
const removedChannels = Object.keys(this.channels).filter(key => !newMults[key]) | |
commonChannels.forEach(key => { | |
if(newMults[key] !== this.mults[key]){ | |
mult.tap(newMults[key], this.channels[key]) | |
mult.untap(this.mults[key], this.channels[key]) | |
} | |
}) | |
addedChannels.forEach(key => { | |
this.channels[key] = chan() | |
mult.tap(newMults[key], this.channels[key]) | |
this.setUpSubscription(key, this.channels[key]) | |
}) | |
removedChannels.forEach(key => { | |
mult.untap(this.mults[key], this.channels[key]) | |
this.channels[key].close() | |
delete this.channels[key] | |
}) | |
this.mults = newMults | |
} | |
unsubscribe() { | |
Object.keys(this.channels).forEach(key => { | |
mult.untap(this.mults[key], this.channels[key]) | |
this.channels[key].close() | |
}) | |
this.channels = {} | |
this.mults = {} | |
} | |
render() { | |
return <ComposedComponent {...this.props} data={this.state.data} /> | |
} | |
} | |
Enhancer.propTypes = ComposedComponent.propTypes | |
Enhancer.contextTypes = ComposedComponent.contextTypes | |
return Enhancer | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is a possible way to implement the Observe API but based on JS-CSP Mults instead of Observables. Some minor benefits can be achieved by using a basic diffing strategy as well.
Usage:
OR
Assuming that getMult returns a mult created from a JS-CSP channel.