Skip to content

Instantly share code, notes, and snippets.

@danprince
Last active April 29, 2016 13:32
Show Gist options
  • Save danprince/6555d2ddd56eeaa2b8286b57ad790549 to your computer and use it in GitHub Desktop.
Save danprince/6555d2ddd56eeaa2b8286b57ad790549 to your computer and use it in GitHub Desktop.
Redux as a Service

Redux as a Service

Hacked together example of usage of Redux as a predictable in memory db with a node http frontend.

Usage

Start the server:

node server.js

Read from the store:

curl localhost:3000/
{"count":0}

curl localhost:3000/count
0

Dispatch an action:

curl localhost:3000/dispatch --data '{ "type": "INC" }'
Successfully dispatched

curl localhost:3000/dispatch --data '{ "type": "INC" }'
Successfully dispatched

Rationale

Could be used to build a flux style firebase clone. Each client connects a websocket, then sends a path selector

const listeners = {
  '/count': {
    path: ['count'],
    callback: function(count) {
      console.log('count changed');
    }
  }
};

The server keeps track of the subscribers, then hooks the sockets to store.subscribe

store.subscribe(function(oldState, newState) {
  for(let { id, path, socket } of subscribers) {
    const oldFragment = selector(path, oldState);
    const newFragment = selector(path, newState);
    if(oldFragment !== newFragment) {
      socket.send(id, newFragment);
    }
  }
});
function Store(reducer, state) {
this.reducer = reducer;
this.state = state;
}
Store.prototype = {
getState: function() {
return this.state;
},
dispatch: function(action) {
const newState = this.reducer(this.state, action);
this.state = newState;
}
};
module.exports = {
createStore: function createStore(reducer, init) {
return new Store(reducer, init);
}
};
const http = require('http');
const redux = require('./redux');
const initState = { count: 0 };
const store = redux.createStore(function rootReducer(state, action) {
switch(action.type) {
case 'INC': return { count: state.count + 1 };
case 'DEC': return { count: state.count - 1 };
default: return state;
}
}, initState);
http.createServer(requestHandler).listen(3000, function(err) {
if(err) throw err;
console.log('Redux on 3000');
});
function lookupPath(path, object) {
return path.reduce((object, key) => {
if(object.hasOwnProperty(key)) {
return object[key];
} else {
return {};
}
}, object);
}
function requestHandler(req, res) {
if(req.url == '/dispatch') {
req.on('data', function(buffer) {
try {
const action = JSON.parse(buffer.toString());
store.dispatch(action);
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Successfully dispatched\n');
} catch(ex) {
res.statusCode = 400;
res.setHeader('Content-Type', 'text/plain');
res.end('Could not parse request\n');
}
});
} else {
const path = req.url.split('/').filter(str => str.length > 0);
const state = store.getState();
const result = lookupPath(path, state);
res.statusCode = (typeof result == 'undefined') ? 404 : 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify(result) + "\n");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment