Last active
January 2, 2018 23:43
-
-
Save jayrbolton/e3aebaeb6462c191c72bb1606872b8f7 to your computer and use it in GitHub Desktop.
different frp app architecture
This file contains hidden or 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
// Usually, streams for the app are created in a tree: | |
// - different event streams from different parts of the page get passed into functions that create objects of streams | |
// - those streams can also get passed into other functions down the tree to create nested objects of streams | |
// The downside of this is that it's hard for different sections of the app to communicate. You might want to access and modify a stream from a branch that is living far down on another branch. Sometimes the order of how streams get created becomes circular | |
// An example is a global notification message stream. You might want to set this in 100 places in your app, but you only want to handle and render it in one place. With the tree structure, you get a lot of repetitive code | |
// To solve this, we can treat the app's object of streams as shallow & *concatenative*, rather than a nested tree | |
// Models take the app's object of streams as parameters and returns an object of streams | |
// Models are chained together in this way; one model takes the other model's ouput as input | |
// Example | |
function searchAjax (input) { | |
const resp = get('/search', input.searchStream) | |
return {resp: resp} | |
} | |
function createAjax (input) { | |
const resp = post('/user', input.createUser) | |
return {resp: resp} | |
} | |
function getResp (input) { | |
return { | |
err: input.resp.filter(r => r.status !== 200), | |
ok: input.resp.filter(r => r.status === 200) | |
} | |
} | |
function loader (input) { | |
return { | |
loading: scanMerge([ | |
[input.err, () => false], | |
[input.ok, () => false], | |
[input.searchStream, () => true] | |
], false) | |
} | |
} | |
function statusMsg (input) { | |
return { | |
errorMsg: flyd.map(input.err, resp => 'Error: ' + resp.body.error), | |
successMsg: flyd.map(input.ok, () => 'Success!') | |
} | |
} | |
// this composes each function and merges every object | |
const app = chain([searchAjax, createAjax, getResp, loader, statusMsg]) | |
// In the above, getResp, loader, and statusMsg all have logic that get reused for any streams | |
// You can add any number of other ajax functions in the beginning of the chain and the functions down the chain will handle their output | |
// Now app is just a simple object of streams: | |
app.searchStream('what') | |
app.createUser({name: 'what'}) | |
app.errorMg() | |
app.successMsg() | |
app.loading() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment