Skip to content

Instantly share code, notes, and snippets.

@geovanisouza92
Created August 20, 2016 00:18
Show Gist options
  • Save geovanisouza92/0f73a5787117e82a26e37c4b5e463464 to your computer and use it in GitHub Desktop.
Save geovanisouza92/0f73a5787117e82a26e37c4b5e463464 to your computer and use it in GitHub Desktop.
"Remote" model for Cycle.js
import {run} from '@cycle/xstream-run'
import {makeDOMDriver, div, button} from '@cycle/dom'
import xs from 'xstream'
function main (sources) {
// Intent
const incAction$ = sources.DOM
.select('.inc').events('click')
.mapTo({type: 'INC'})
const decAction$ = sources.DOM
.select('.dec').events('click')
.mapTo({type: 'DEC'})
const action$ = xs.merge(
incAction$,
decAction$
)
// View
const vtree$ = sources.ws
.map(state =>
div([
button('.inc', '+1'),
button('.dec', '-1'),
div(`Count: ${state.count}`)
])
)
const sinks = {
DOM: vtree$,
ws: action$,
}
return sinks
}
function makeWSDriver (ws) {
return function driver (msg$) {
msg$.addListener({
next: msg => {
ws.send(JSON.stringify(msg))
},
error: console.error.bind(console),
complete: () => console.log('Closed')
})
return xs.create({
start: listener => {
ws.onmessage = msg => listener.next(JSON.parse(msg.data))
},
stop: () => {}
})
}
}
run(main, {
DOM: makeDOMDriver('#app'),
ws: makeWSDriver(new WebSocket('ws://localhost:8080'))
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Remote model</title>
</head>
<body>
<div id="app"></div>
<script src="dist/bundle.js"></script>
</body>
</html>
{
"name": "remotemodel2",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"prebuild": "mkdirp dist",
"build": "browserify src/client.js -d -t babelify --outfile dist/bundle.js",
"start": "npm run build && babel-node src/server.js"
},
"author": "Geovani de Souza <geovanisouza92@gmail.com>",
"license": "ISC",
"dependencies": {
"@cycle/dom": "^12.1.0",
"@cycle/xstream-run": "^3.0.4",
"xstream": "^5.3.6",
"ws": "^1.1.1"
},
"devDependencies": {
"babel-cli": "^6.11.4",
"babel-preset-es2015": "^6.13.2",
"babel-register": "^6.11.6",
"babelify": "^7.3.0",
"browserify": "^13.1.0",
"mkdirp": "^0.5.1"
}
}
import Cycle from '@cycle/xstream-run'
import {Server as WebSocketServer} from 'ws'
import xs from 'xstream'
function backend (sources) {
// Model
const state$ = sources.ws
.debug('action$')
.map(action => {
switch (action.type) {
case 'INC': return count => count + 1
case 'DEC': return count => count - 1
default: return count => count
}
})
.fold((count, reducer) => reducer(count), 0)
.map(count => ({count}))
.debug('state$')
const sinks = {
ws: state$
}
return sinks
}
function makeWSDriver (ws) {
return function driver (msg$) {
msg$.addListener({
next: msg => {
ws.send(JSON.stringify(msg))
},
error: console.error.bind(console),
complete: () => console.log('Closed')
})
return xs.create({
start: listener => {
ws.on('message', msg => listener.next(JSON.parse(msg)))
},
stop: () => {}
})
}
}
const wss = new WebSocketServer({port: 8080})
wss.on('connection', ws => {
const dispose = Cycle.run(backend, {
ws: makeWSDriver(ws)
})
ws.on('close', dispose)
})
console.log('Ready')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment