A simpler implementation of React.JS's Flux
var EventEmitter = require('events').EventEmitter, | |
_ = require('lodash'); | |
/** | |
* Creates an action functor object | |
*/ | |
exports.createAction = function() { | |
var action = new EventEmitter(), | |
eventLabel = "action", | |
functor; | |
functor = function() { | |
action.emit(eventLabel, Array.prototype.slice.call(arguments, 0)); | |
}; | |
/** | |
* Subscribes the given callback for action triggered | |
* | |
* @param {Function} callback The callback to register as event handler | |
* @param {Mixed} [optional] bindContext The context to bind the callback with | |
* @returns {Function} Callback that unsubscribes the registered event handler | |
*/ | |
functor.listen = function(callback, bindContext) { | |
var eventHandler = function(args) { | |
callback.apply(bindContext, args); | |
}; | |
action.addListener(eventLabel, eventHandler); | |
return function() { | |
action.removeListener(eventLabel, eventHandler); | |
}; | |
}; | |
return functor; | |
}; | |
/** | |
* Creates an event emitting Data Store | |
* | |
* @param {Object} definition The data store object definition | |
*/ | |
exports.createStore = function(definition) { | |
var store = new EventEmitter(), | |
eventLabel = "change"; | |
function Store() { | |
if (this.init && _.isFunction(this.init)) { | |
this.init(); | |
} | |
} | |
_.assign(Store.prototype, definition); | |
Store.prototype.listenTo = function(listenable, callback) { | |
if (!_.isFunction(listenable.listen)) { | |
throw new TypeError(listenable + " is missing a listen method"); | |
} | |
return listenable.listen(callback, this); | |
}; | |
Store.prototype.listen = function(callback, bindContext) { | |
var eventHandler = function(args) { | |
callback.apply(bindContext, args); | |
}; | |
store.addListener(eventLabel, eventHandler); | |
return function() { | |
action.removeListener(eventLabel, eventHandler); | |
}; | |
}; | |
Store.prototype.trigger = function() { | |
var args = Array.prototype.slice.call(arguments, 0); | |
store.emit(eventLabel, args); | |
}; | |
return new Store(); | |
}; |
var Reflux = require('./src/reflux'); | |
// Creating an Action | |
var textUpdate = Reflux.createAction(); | |
var statusUpdate = Reflux.createAction(); | |
// Creating a Data Store - Listening to textUpdate action | |
var textStore = Reflux.createStore({ | |
init: function() { | |
this.listenTo(textUpdate, this.output); | |
}, | |
output: function() { | |
var i, args = Array.prototype.slice.call(arguments, 0); | |
for (i = 0; i < args.length; i++) { | |
this.writeOut(args[i]); | |
} | |
}, | |
writeOut: function(text) { | |
this.trigger(text); | |
} | |
}); | |
// Creating a DataStore | |
var statusStore = Reflux.createStore({ | |
init: function() { | |
this.listenTo(statusUpdate, this.output); | |
}, | |
output: function(flag) { | |
var status = flag ? 'ONLINE' : 'OFFLINE'; | |
this.trigger(status); | |
} | |
}); | |
// Creating an aggregate DataStore that is listening to textStore and statusStore | |
var storyStore = Reflux.createStore({ | |
init: function() { | |
this.listenTo(statusStore, this.statusChanged); | |
this.listenTo(textStore, this.textUpdated); | |
this.storyArr = []; | |
}, | |
statusChanged: function(flag) { | |
if (flag === 'OFFLINE') { | |
this.trigger('Once upon a time the user did the following: ' + this.storyArr.join(', ')); | |
// empty storyArr | |
this.storyArr.splice(0, this.storyArr.length); | |
} | |
}, | |
textUpdated: function(text) { | |
this.storyArr.push(text); | |
} | |
}); | |
// Fairly simple view component that outputs to console | |
function ConsoleComponent() { | |
textStore.listen(function(text) { | |
console.log('text: ', text); | |
}); | |
statusStore.listen(function(status) { | |
console.log('status: ', status); | |
}); | |
storyStore.listen(function(story) { | |
console.log('story: ', story); | |
}); | |
}; | |
var consoleComponent = new ConsoleComponent(); | |
// Invoking the action with arbitrary parameters | |
statusUpdate(true); | |
textUpdate("testing", 1337, { "test": 1337 }); | |
statusUpdate(false); | |
/** Will output the following: | |
* | |
* status: ONLINE | |
* text: testing | |
* text: 1337 | |
* text: { test: 1337 } | |
* story: Once upon a time the user did the following: testing, 1337, [object Object] | |
* status: OFFLINE | |
*/ |
This comment has been minimized.
This comment has been minimized.
Find a typo in reflux.js (line 67): |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
I've created a project for this, it is up at github.