diff options
Diffstat (limited to 'README.md')
| -rw-r--r-- | README.md | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ccd1fd --- /dev/null +++ b/README.md @@ -0,0 +1,169 @@ +# Grafn + +Graph + Fn: Execute functions as a graph. + +## What it's for? + +Grafn lets you execute sequences of async functions by defining them as +vertices in a graph. + +This allows you to easily define and manipulate complex dependencies in +asynchronous code. + +## How can I use it? + +In order to use it you must first create a graph. + +```javascript +const Grafn = require('grafn'); + +const graph = new Grafn(); +``` + +Next you need to add some vertexes. + +```javascript +graph.vertex({ + name: 'root', + action() { + + return 5; + } +}); +``` + +This is a vertex without dependencies, it means it can be executed without +waiting for anything else. The return value of this function will be stored +so it can be used by its dependents. + +You can add dependencies by listing the names as an array in the vertex definition. + +```javascript +graph.vertex({ + name: 'addition', + dependencies: ['root'], + action(state) { + + return state.root + state.root; + } +}); +``` + +Notice how the result of the `root` vertex is available in this action. + +Vertexes will be executed as soon as all of their dependencies are met. For +example, consider the following graph + +```javascript +const Grafn = require('grafn'); + +const graph = new Grafn(); + +graph.vertex({ + name: 'root', + action() { + + return 5; + } +}); + +graph.vertex({ + name: 'addition', + dependencies: ['root'], + action(state) { + + return state.root + state.root; + } +}); + +graph.vertex({ + name: 'subtraction', + dependencies: ['root'], + action(state) { + + return state.root - state.root; + } +}); + +graph.vertex({ + name: 'multiplication', + dependencies: ['root'], + action(state) { + + return state.root * state.root; + } +}); + +graph.vertex({ + name: 'division', + dependencies: ['root'], + action(state) { + + return state.root / state.root; + } +}); + +graph.vertex({ + name: 'tally', + dependencies: ['addition', 'subtraction', 'multiplication', 'division'], + action(state) { + + console.log('+', state.addition); + console.log('-', state.subtraction); + console.log('*', state.multiplication); + console.log('/', state.division); + } +}); +``` + +The `addition`, `subtraction`, `multiplication`, and `division` vertices will +all run as soon as `roott` is executed. However, the final `tally` vertex won't +run until all other operations are complete. + +You can visualize the graph by using the `graph.toString()` method. This +will output a graphviz digraph: + +```graphviz +digraph { + root + addition + root -> addition + subtraction + root -> subtraction + multiplication + root -> multiplication + division + root -> division + tally + addition -> tally + subtraction -> tally + multiplication -> tally + division -> tally +} +``` + +![execution graph, before execution][graph-pre-exec] + +You can easily change the shape of the graph by changing the dependencies array. + +In order to start execution of the graph you should select which node to start +from. + +``` +graph.run('root'); +``` + +After an execution, you can use `graph.toString()` to check the result of an +execution. It will highlight which nodes were executed successfully (green), and +which nodes threw an error (red). + +![execution graph, after execution][graph-post-exec] + +## Acknowledgements + +This project implements the same ideas behind [fluorine][fluorine], a similar +graph based library. Grafn wouldn't exist without it. + +[fluorine]: https://github.com/freshout-dev/fluorine +[graph-pre-exec]: doc/images/graph-pre-exec.svg +[graph-post-exec]: doc/images/graph-post-exec.svg |