Package Exports
- choo-pull
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (choo-pull) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
choo-pull 
Wrap handlers to use pull-stream in a choo
plugin.
This is intended to go beyond basic choo
usage, and tread into the domain of
managing asynchronous complexity using streams / FRP.
While streams code takes longer to write up front, resulting code is generally
stateless, pretty damn fast and surprisingly reusable. pull-streams
are a
minimal version of streams that weigh 200 bytes and handle backpressure
phenomenally.
Usage
const pull = require('choo-pull')
const choo = require('choo')
const app = choo()
app.use(pull())
const tree = app.start()
document.body.appendChild(tree)
Now each handler in a model
expects a valid through
pull-stream to be
returned synchronously. Initial data will be passed as the source, errors
handling and done()
calls are appended in the sink:
const through = require('pull-through')
const ws = require('pull-ws')
const xhr = require('xhr')
module.exports = {
namespace: 'my-model',
state: {
count: 0
},
reducers: {
increment: (data, state) => ({ count: state.count + data }),
decrement: (data, state) => ({ count: state.count - data }),
},
subscriptions: {
getDataFromSocket: (Send$) => {
const ws$ = Ws$('wss://echo.websocket.org')
return pull(ws$, Deserialize$(), Send$('performXhr'))
}
},
effects: {
performXhr: (state, Send$) => pull(Xhr$(), Deserialize$())
}
}
function Xhr$ () {
return through((data, cb) => {
xhr('/foo/bar', { data: data }, (err, res) => {
if (err) return cb(err)
cb(null, res)
})
})
}
function Deserialize$ () {
return through((data, cb) {
try {
cb(null, JSON.parse(data))
} catch (e) {
cb(e)
}
})
}
function Ws$ (url) {
return ws(new window.WebSocket(url))
}
Using send()
Like all other API methods, so too does the send()
method become a
pull-stream
. More specifically it becomes a through
stream that takes the
action
name as the sole arugment, and pushes any results into any a
connecting through
or sink
stream:
const through = require('pull-through')
module.exports = {
state: {
count: 0
},
reducers: {
bar: (state) => ({ state.count + data })
},
effects: {
callBar: (state, prev, Send$) => Send$('bar'),
callFoo: (state, prev, Send$) => Send$('foo')
}
}
// send('callFoo', 1)
// => state.count = 1
API
hooks = pull(opts)
Create an object of hooks that can be passed to app.use()
. Internally ties
into the following hooks:
- wrapSubscriptions: changes the API of
subscriptions
to be(Send$)
- wrapEffects: changes the API of
effects
to be(state, Send$)
The following options can be passed:
- opts.subscriptions: default:
true
. Determine ifsubscriptions
should be wrapped - opts.effects: default:
true
. Determine ifeffects
should be wrapped
Incrementally enabling options can be useful when incrementally upgrading from a CSP-style codebase to a reactive / streaming one.
pull.subscription(subscription)
Wrap a single subscription
. Useful to incrementally upgrade a CSP-style
codebase to a reactive / streaming one.
pull.effect(effect)
Wrap a single effect
. Useful to incrementally upgrade a CSP-style
codebase to a reactive / streaming one.
FAQ
Why aren't reducers wrapped in pull-streams?
In choo@3
the internal workings demand that data always be returned
synchronously. Because pull-stream
returns data in a callback, reducers
cannot be wrapped. Perhaps at some point we'll allow for a hybrid API, but at
this point it's frankly not possible.
Installation
$ npm install choo-pull