Comparing version 0.2.1 to 0.2.2
{ | ||
"name": "reflux", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"homepage": "https://github.com/spoike/reflux", | ||
@@ -5,0 +5,0 @@ "authors": [ |
{ | ||
"name": "reflux", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"description": "A simple library for uni-directional dataflow application architecture inspired by ReactJS Flux", | ||
"main": "src/index.js", | ||
"main": "index.js", | ||
"scripts": { | ||
@@ -7,0 +7,0 @@ "test": "grunt test", |
@@ -41,3 +41,3 @@ # RefluxJS | ||
Reflux has refactored Flux to be a bit more dynamic and be more FRP friendly: | ||
Reflux has refactored Flux to be a bit more dynamic and be more Functional Reactive Programming (FRP) friendly: | ||
@@ -115,2 +115,57 @@ * The singleton dispatcher is removed in favor for letting every action act as dispatcher instead. | ||
#### Asynchronous actions | ||
For actions that represent asynchronous operations (e.g. API calls), a few separate dataflows result from the operation. In the most typical case, we consider completion and failure of the operation. To create related actions for these dataflows, which you can then access as attributes, use `options.children`. | ||
```javascript | ||
// this creates 'load', 'load.completed' and 'load.failed' | ||
var Actions = Reflux.createActions({ | ||
"load": {children: ["completed","failed"]} | ||
}); | ||
// when 'load' is triggered, call async operation and trigger related actions | ||
Actions.load.listen( function() { | ||
// By default, the listener is bound to the action | ||
// so we can access child actions using 'this' | ||
someAsyncOperation() | ||
.then( this.completed ) | ||
.catch( this.failed ); | ||
}); | ||
``` | ||
There is a shorthand to define the `completed` and `failed` actions in the typical case: `options.asyncResult`. The following are equivalent: | ||
```javascript | ||
createAction({ | ||
children: ["progressed","completed","failed"] | ||
}); | ||
createAction({ | ||
asyncResult: true, | ||
children: ["progressed"] | ||
}); | ||
``` | ||
There are a couple of helper methods available to trigger the `completed` and `failed` actions: | ||
* `promise` - Expects a promise object and binds the triggers of the `completed` and `failed` child actions to that promise, using `then()` and `catch()`. | ||
* `listenAndPromise` - Expects a function that returns a promise object, which is called when the action is triggered, after which `promise` is called with the returned promise object. Essentially calls the function on trigger of the action, which then triggers the `completed` or `failed` child actions after the promise is fulfilled. | ||
Therefore, the following are all equivalent: | ||
```javascript | ||
asyncResultAction.listen( function(arguments) { | ||
someAsyncOperation(arguments) | ||
.then(asyncResultAction.completed) | ||
.catch(asyncResultAction.failed); | ||
}); | ||
asyncResultAction.listen( function(arguments) { | ||
asyncResultAction.promise( someAsyncOperation(arguments) ); | ||
}); | ||
asyncResultAction.listenAndPromise( someAsyncOperation ); | ||
``` | ||
#### Action hooks | ||
@@ -117,0 +172,0 @@ |
@@ -1,2 +0,2 @@ | ||
var Reflux = require('../src'), | ||
var Reflux = require('./index'), | ||
_ = require('./utils'); | ||
@@ -3,0 +3,0 @@ |
var _ = require('./utils'), | ||
Reflux = require('../src'), | ||
Reflux = require('./index'), | ||
Keep = require('./Keep'), | ||
@@ -13,5 +13,8 @@ allowed = {preEmit:1,shouldEmit:1}; | ||
*/ | ||
module.exports = function(definition) { | ||
var createAction = function(definition) { | ||
definition = definition || {}; | ||
if (!_.isObject(definition)){ | ||
definition = {name: definition}; | ||
} | ||
@@ -34,2 +37,13 @@ for(var a in Reflux.ActionMethods){ | ||
definition.children = definition.children || []; | ||
if (definition.asyncResult){ | ||
definition.children = definition.children.concat(["completed","failed"]); | ||
} | ||
var i = 0, childActions = {}; | ||
for (; i < definition.children.length; i++) { | ||
var name = definition.children[i]; | ||
childActions[name] = createAction(name); | ||
} | ||
var context = _.extend({ | ||
@@ -45,3 +59,3 @@ eventLabel: "action", | ||
_.extend(functor,context); | ||
_.extend(functor,childActions,context); | ||
@@ -53,1 +67,3 @@ Keep.createdActions.push(functor); | ||
}; | ||
module.exports = createAction; |
var _ = require('./utils'), | ||
Reflux = require('../src'), | ||
Reflux = require('./index'), | ||
Keep = require('./Keep'), | ||
@@ -21,3 +21,3 @@ allowed = {preEmit:1,shouldEmit:1}, | ||
if (!allowed[a] && (Reflux.PublisherMethods[a] || Reflux.ListenerMethods[a])){ | ||
throw new Error("Cannot override API method " + a + | ||
throw new Error("Cannot override API method " + a + | ||
" in Reflux.StoreMethods. Use another method name or override it on Reflux.PublisherMethods / Reflux.ListenerMethods instead." | ||
@@ -30,3 +30,3 @@ ); | ||
if (!allowed[d] && (Reflux.PublisherMethods[d] || Reflux.ListenerMethods[d])){ | ||
throw new Error("Cannot override API method " + d + | ||
throw new Error("Cannot override API method " + d + | ||
" in store creation. Use another method name or override it on Reflux.PublisherMethods / Reflux.ListenerMethods instead." | ||
@@ -42,2 +42,3 @@ ); | ||
this.eventLabel = "change"; | ||
bindMethods(this, definition); | ||
if (this.init && _.isFunction(this.init)) { | ||
@@ -57,3 +58,2 @@ this.init(); | ||
var store = new Store(); | ||
bindMethods(store, definition); | ||
Keep.createdStores.push(store); | ||
@@ -60,0 +60,0 @@ |
@@ -32,2 +32,3 @@ exports.ActionMethods = require('./ActionMethods'); | ||
var _ = require('./utils'); | ||
@@ -37,9 +38,12 @@ /** | ||
* | ||
* @param actionNames the names for the actions to be created | ||
* @param definitions the definitions for the actions to be created | ||
* @returns an object with actions of corresponding action names | ||
*/ | ||
exports.createActions = function(actionNames) { | ||
var i = 0, actions = {}; | ||
for (; i < actionNames.length; i++) { | ||
actions[actionNames[i]] = exports.createAction(); | ||
exports.createActions = function(definitions) { | ||
var actions = {}; | ||
for (var k in definitions){ | ||
var val = definitions[k], | ||
actionName = _.isObject(val) ? k : val; | ||
actions[actionName] = exports.createAction(val); | ||
} | ||
@@ -46,0 +50,0 @@ return actions; |
@@ -5,2 +5,45 @@ var _ = require('./utils'), | ||
/** | ||
* Extract child listenables from a parent from their | ||
* children property and return them in a keyed Object | ||
* | ||
* @param {Object} listenable The parent listenable | ||
*/ | ||
mapChildListenables = function(listenable) { | ||
var i = 0, children = {}; | ||
for (;i < (listenable.children||[]).length; ++i) { | ||
childName = listenable.children[i]; | ||
if(listenable[childName]){ | ||
children[childName] = listenable[childName]; | ||
} | ||
} | ||
return children; | ||
}; | ||
/** | ||
* Make a flat dictionary of all listenables including their | ||
* possible children (recursively), concatenating names in camelCase. | ||
* | ||
* @param {Object} listenables The top-level listenables | ||
*/ | ||
flattenListenables = function(listenables) { | ||
var flattened = {}; | ||
for(var key in listenables){ | ||
var listenable = listenables[key]; | ||
var childMap = mapChildListenables(listenable); | ||
// recursively flatten children | ||
var children = flattenListenables(childMap); | ||
// add the primary listenable and chilren | ||
flattened[key] = listenable; | ||
for(var childKey in children){ | ||
var childListenable = children[childKey]; | ||
flattened[key + _.capitalize(childKey)] = childListenable; | ||
} | ||
} | ||
return flattened; | ||
}; | ||
/** | ||
* A module of methods related to listening. | ||
@@ -36,7 +79,8 @@ */ | ||
listenToMany: function(listenables){ | ||
for(var key in listenables){ | ||
var allListenables = flattenListenables(listenables); | ||
for(var key in allListenables){ | ||
var cbname = _.callbackName(key), | ||
localname = this[cbname] ? cbname : this[key] ? key : undefined; | ||
if (localname){ | ||
this.listenTo(listenables[key],localname,this[cbname+"Default"]||this[localname+"Default"]||localname); | ||
this.listenTo(allListenables[key],localname,this[cbname+"Default"]||this[localname+"Default"]||localname); | ||
} | ||
@@ -43,0 +87,0 @@ } |
@@ -1,2 +0,2 @@ | ||
var Reflux = require('../src'); | ||
var Reflux = require('./index'); | ||
@@ -3,0 +3,0 @@ |
@@ -1,2 +0,2 @@ | ||
var Reflux = require('../src'); | ||
var Reflux = require('./index'); | ||
@@ -3,0 +3,0 @@ /** |
@@ -35,2 +35,3 @@ var _ = require('./utils'); | ||
listen: function(callback, bindContext) { | ||
bindContext = bindContext || this; | ||
var eventHandler = function(args) { | ||
@@ -46,2 +47,43 @@ callback.apply(bindContext, args); | ||
/** | ||
* Attach handlers to promise that trigger the completed and failed | ||
* child publishers, if available. | ||
* | ||
* @param {Object} The promise to attach to | ||
*/ | ||
promise: function(promise) { | ||
var me = this; | ||
var canHandlePromise = | ||
this.children.indexOf('completed') >= 0 && | ||
this.children.indexOf('failed') >= 0; | ||
if (!canHandlePromise){ | ||
throw new Error('Publisher must have "completed" and "failed" child publishers'); | ||
} | ||
promise.then(function(response) { | ||
return me.completed(response); | ||
}).catch(function(error) { | ||
return me.failed(error); | ||
}); | ||
}, | ||
/** | ||
* Subscribes the given callback for action triggered, which should | ||
* return a promise that in turn is passed to `this.promise` | ||
* | ||
* @param {Function} callback The callback to register as event handler | ||
*/ | ||
listenAndPromise: function(callback, bindContext) { | ||
var me = this; | ||
bindContext = bindContext || this; | ||
return this.listen(function() { | ||
var args = arguments, | ||
promise = callback.apply(bindContext, args); | ||
return me.promise.call(me, promise); | ||
}, bindContext); | ||
}, | ||
/** | ||
* Publishes an event using `this.emitter` (if `shouldEmit` agrees) | ||
@@ -48,0 +90,0 @@ */ |
@@ -34,4 +34,8 @@ /* | ||
exports.capitalize = function(string){ | ||
return string.charAt(0).toUpperCase()+string.slice(1); | ||
}; | ||
exports.callbackName = function(string){ | ||
return "on"+string.charAt(0).toUpperCase()+string.slice(1); | ||
return "on"+exports.capitalize(string); | ||
}; | ||
@@ -38,0 +42,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
60251
27
842
580
0