function-tree
Install
NPM
npm install function-tree
Description
Function-tree is the what Cerebral extends to create its signal implementation. You can use this library on the server, or standalone in the client as a replacement for Cerebral. Basically a function-tree allows you to execute a tree of functions. You can use the Cerebral debugger to debug function tree execution in any JS environment.
Function-tree is somewhat in the same family as Rxjs and Promises. The main difference is that Rxjs and Promises are based on value transformation. That means only the value returned from the previous function is available in the next. This works when you indeed want to transform values, but events in your application are rarely about value transformation, they are about running side effects and going through one of multiple execution paths. Function tree embraces the fact that most of what we do in application development is running side effects.
Rxjs and Promises are also about execution control, but neither of them have declarative conditional execution paths, you have to write an IF or SWITCH statement or decouple streams. With function tree you are able to diverge the execution down paths just as declaratively as functions. This helps readability.
Instantiate
// Node:// const FunctionTree = require('function-tree').FunctionTree const ft = // add side effect libraries to context ft
You can also add multiple custom context providers by using an array:
const ft = // add side effect libraries to context uuid axios
errors
FunctionTreeError (base)
// Node:// const FunctionTreeError = require('function-tree').FunctionTreeError // Error structure name: 'FunctionTreeError' message: 'Some function-tree error' stack: '...'
FunctionTreeExecutionError
// Node:// const FunctionTreeExecutionError = require('function-tree').FunctionTreeExecutionError // Error structure name: 'FunctionTreeExecutionError' message: 'Some execution error' execution: name: 'someName' funcDetails: name: 'someFunction' functionIndex: 5 payload: foo: 'bar' stack: '...'
devtools
Download the function tree standalone debugger for Mac, Windows or Linux.
// Node:// const FunctionTree = require('function-tree').FunctionTree// const Devtools = require('function-tree/devtools').Devtools const devtools = // Set url of remote debugger host: 'localhost:8585' // By default debugger tries to reconnect when it is not active reconnect: true // By default devtools connects to "ws://". This option should be set to true // when browser operates on https. Follow debugger instructions for // further configuration https: falseconst ft = // Add your function tree to the debuggerdevtools // If you are not going to use it anymore, remove itdevtools // Remove all function trees from debuggerdevtools
sequence
You can use an array literal to define a sequence of functions.
{} {} moduleexports = someFunction someOtherFunction
Or you can be explicit by using the sequence function:
// Node:// const sequence = require('function-tree').sequence {} {} moduleexports =
The first argument to sequence can be a string, which names the sequence. This will be shown in the debugger. If it is the root sequence it will be used as the name of the execution itself.
// Node:// const sequence = require('function-tree').sequence {} {} moduleexports =
parallel
// Node:// const sequence = require('function-tree').parallel {} {} moduleexports =
Even though someFunction returns a Promise, someOtherFunction will be run immediately.
context
path
The path is only available on the context when the function can diverge the execution down a path.
// Node:// const FunctionTree = require('function-tree').FunctionTree { contextpropsfoo // "bar" return contextpath} { contextpropsfoo // "bar" contextpropsfoo2 // "bar2" return { }} { contextpropsfoo // "bar" contextpropsfoo2 // "bar2" contextpropsfoo3 // "bar3"} const ft = {}const tree = funcA pathA: funcB funcC pathB: ft
props
// Node:// const FunctionTree = require('function-tree').FunctionTree { contextpropsfoo // "bar"} const ft = const tree = funcA ft
error
// Node:// const FunctionTree = require('function-tree').FunctionTreeconst ft = {} // As an event (async)ft // As callback for single execution// Triggers sync/async depending on where error occursft // As callback (sync)ft
Provider
You can create your own custom providers which exposes the domain specific API you need for your application. You can also use it to set defaults for side effects, or even just transform the API more to your liking. With a Provider the debugger will know about the executions and inform you which functions executed them.
// Node:// const FunctionTree = require('function-tree').Provider const http = { return axios } const api = { return thiscontexthttp } const ft = http api
tags
Tags gives you more power to write declarative code.
createTemplateTag
Allows you to add new tags, targeting your custom providers.
const myTag =
Example use
someChain =
extractValueWithPath
Easy way to support nested values extraction from objects using the path.
const myTag =
props
Targets the props passed into the execution of a function tree:
resolveObject
Wraps an object passed to a function factory, resolving any template tags.
const mychain =
ResolveProvider
By default your function tree instance includes the ResolveProvider. It allows you to evaluate tags.
{ { // Evaluates to the contextual value's value, if not a contextual value // it will just return the value. resolvevaluesomeValue // Evaluates the path in the tag (someValue must be a Tag). resolve // Evaluates if variable is a tag. We can optionally pass an array of // types such as ['props', 'string'] as second argument. resolve // Evaluates if variable is a ResolveValue. Useful when you have created custom // stuff to be evaluated in tags or other, extending ResolveValue class. resolve } return myFunction}
ResolveValue
Allows you to create a custom tag value container.
{ super thistag = tag } // Required method { return thistag } { return tag}
Example use
string
Returns the evaluated string.
events
The execute function is also an event emitter.
// Node:// const FunctionTree = require('function-tree').FunctionTree const ft = const tree = funcA // When an error is thrown, also catches promise errorsft // When a function tree is executedft // When a function tree execution has endedft // When a function tree goes down a pathft // When a function tree ends execution of a pathft // When a function in a function tree starts executingft // When a function in a function tree stops executingft // Triggers when an async function has been runft // When a parallel execution is about to happen (array in array)ft // When a function in parallel execution is done executingft // When a parallel execution is doneft ft