st8flo
v0.5.0
Published
TBD
Downloads
30
Maintainers
Readme
St8Flo
Software can be complicated, with lots of moving parts that often work together, and more often not. Leading to complicated semantic bugs that are hard to foresee, or get rid of.
St8Flo brings a simple dataflow like style of code architecture to JS, along with reactivity and execution tracking, in order to keep code manageable, predictable, and visually traceable in case of errors.
Based on vanilla javascript, and has only lodash as a dependency.
So should be easy to integrate with most JS front-end or back-end frameworks.
Installation
npm install st8flo --save
bower install st8flo --save
Basic usage
Quickly define the overall architecture of your app, as a sequence of actions (FloSt8).
You can use FlowSt8s to transform input data into output data (data flow), or simply as function containers that manage the execution sequence of your functions (control flow). Result data returned by one FloSt8, will get passed, as input to the next.
var mf = St8.Flo('mainFlow')
.start()
.pipe('child1') // Quickly create an empty FloSt8, to be filled later.
.pipe(['child2', 'child3']); // Create multiple empty FloSt8s
mf.__('child2') // Select one of the above FloSt8s
.pipe('child4'); // Child4 is now connected under Child2
mf.__('child3') // Child5 is now connected under child3
.pipe('child5');
Use Markers to mark important events / execution checkpoints.
Can be created on the fly. For eg: DOM button click event Or a login callback with success/fail as the value. Or in app's network status callback to mark disconnections.
St8.marker('online').set(false);
Assign functions / conditions to the FloSt8s, anywhere in your code.
Optional and can only be done once per FloSt8 If not assigned, the FloSt8 simply passes the data forward to the next FloSt8 in the chain.
St8('child1')
.when( { marker1 : true } )
.do(function(input){
// your function code goes here.
});
Return a promise for handling async functions, or return normally, for sync functions. Returned / resolved values get passed as input to the next FlowSt8.
Finally, trigger the flow.
mf.trigger(data, signalData);
You can call this from anywhere in your app. For eg - in a DOM click callback for the login button.
The magic sauce - FloSt8 Behaviour
1> Common behaviour but independent data - All FloSt8s with the same name, no matter which flow (or flows) they are piped to, will always share the same execution conditions and function, but have independent data paths.
ie. Data from one flow will never conflict with data in another, even if both have the same 'child1' FloSt8.
2> FloSt8's will WAIT - for all specified conditions to become valid before execution.
It doesn't matter if the execution flow arrives at a FloSt8 too early. Once triggered, It will automatically resume execution from where it left off, whenever the conditions become valid again.
3> Reactivity - A special type of FloSt8 can self activate, the moment all specified conditions become valid, without needing to be triggered by a parent FloSt8.
4> Both sync & async - functions are handled seamlessly and uses native Promises, under the hood.
5> FloSt8s can also skip incoming data without passing it down or breaking the Flo chain. Useful to eliminate invalid or empty data objects. Plus, special pre-defined types of FloSt8s can be used to control flow, and iterate over arrays within the input data, as well. Eg: skipIF, forEach etc.
Try it out :
Codepen
https://codepen.io/anon/pen/EQWjjR?editors=0012
Browser console
Include dependencies
Either install lodash & st8flo.js,
Or copy paste below script in the browser console ! This will import the dependencies using script tags.
// Include dependencies within browser console. Tested in google chrome
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js';
document.head.appendChild(script);
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/st8flo.js';
document.head.appendChild(script);
Once included, copy paste this code in the console, to try out St8Flo !
//----------- Quickly define the overall architecture of your app -------------
var mf = St8.Flo('mainFlow')
.start()
.pipe('child1') // Quickly create an empty FloSt8, to be filled later.
.pipe(['child2', 'child3']); // Create multiple empty FloSt8s
mf.__('child2') // Select one of the above FloSt8s
.pipe('child4') // Child4 is connected under Child2
.pipe('child6');
mf = mf.__('child3') // Child5 is connected to child3
.pipe('child5')
.pipe('child7')
.terminal('done')
.end();
// --------- Use markers anywhere within your app ------------
// One is set here, another after the flow is triggered at the bottom.
St8.Marker('marker1').set(true);
// ----------- Define your FloSt8s ------------
St8('child2')
.when({
marker1: true
})
.do(function (input) {
console.log('--> Child 2 got - ', input);
return input + ' + candy from Child2';
});
// Simulate an async FloSt8 that finishes after 3 seconds.
St8('child4')
.do(function (input) {
return new Promise(function (resolve, reject) {
console.log('--> Child4 got - ',input);
console.log('\t ** Child4 is going out to async for 10 seconds !');
setTimeout(function () {
console.log('\n\n\t--------- Child4 is back home after 10 seconds !');
resolve(input + ' and Child4');
}, 10000);
});
});
St8('child6')
.do(function (input) {
console.log('--> Child6 just woke up and got - ', input);
});
//---------------
St8('child3')
.when({
IAmBack: true
})
.do(function (input) {
console.log('--> Child 3 got - ', input);
return input + ' + some stuff (thats not quite candy) from Child3';
});
St8('child5')
.do(function (input) {
console.log('--> Child5 woke up & got - ', input);
return input + ' and Child5';
});
St8('child7')
.do(function (input) {
console.log('--> Child7 woke up & got - ', input);
return input;
});
console.log("\n\nSetup DONE.\n\n");
// Simulate async process and set marker2 to true after 10 secs.
console.log("Simulating async process - I'm going to wake up Child3 after 5 seconds. Setting a timeout.\n\n");
setTimeout(function () {
console.log("\n\n");
console.log("--------- I'm back after 5 seconds. Where's Child3 at ? \n\n");
St8.Marker('IAmBack').set(true);
}, 5000);
/* ===============================
Finally trigger the flow and simulate an async process.
*/
console.log("Meanwhile, let others get their gifts...\n\n");
mf.trigger(' my gift ');
Work in progress. Feel free to open issues