Flow.js
Flow.js is a small yet powerful callback synchronizer for browsers and Node.js. A powerful alternative to Promise based structure, Flow.js offers you greater control, cleaner syntax and consistency across various platforms, all in a tiny package with virtually no overhead.
fn: loadTemplate success: parseTemplate fn: getUserData success: processUserData fn: renderUI sync: true fn: getUserAlbums success: processUserAlbums fn: getAlbumImages success: renderAlbumImages sync: true;
Contents
Node.js installation and usage
To use Flow.js in Node.js projects, install its npm package.
npm install flow-sync
Usage:
var Flow = ; ...;
Tasks
When creating a new Flow object you provide it with an array
of tasks.
A task can be a function with callbacks (an AJAX call for example) or another sub-flow.
Flow is not a queue - tasks in the flow will execute in parallel by default.
Anatomy of a task
A task is an object
with a number of attributes that define its behavior.
Example:
fn: getUserAlbums success: processUserAlbums fail: onError
Task properties
Property | Description | Accepts | Default |
---|---|---|---|
fn |
A function to be executed. | function |
N/A |
flow |
A sub-flow to be executed. If provided, fn will be ignored. |
new Flow() |
N/A |
success |
A callback function to execute when the task is to be completed. | function |
Empty function(){} |
fail |
A callback function to execute when if the task fails for any reason. Under default conditions executing fail() will stop the flow. |
function |
Empty function(){} |
sync |
If set as true will cause the task to await the completion of all previous tasks in the flow before executing. |
boolean |
false or true if defaultSync options is used |
failRetries |
The number of times to repeat the task in case of failing. | integer |
0 |
retryInterval |
An interval (in milliseconds) between retry attempts. Used in conjunction with failRetries . |
integer or function |
0 |
continueOnFail |
If set as true the failing of the task will not cause the entire flow to fail. |
boolean |
false |
-
Accepts:
function(success, fail)
A function to be executed. The function receives a mandatory
success
and an optionalfail
functions.{;}{;}fn: myFunctionfn: myOtherFunction;// Log:// Completed 1 true// Completed {a: 1, b: 2}As we can see from the example above, after 1000 milliseconds we execute the
success
function with attributes we want it to receive.Please note: Execution of the
success
orfail
function is mandatory, otherwise the task will not finish and the flow will never be completed.Let's see another example using jQuery to get AJAX data.
{$;}fn: getUserAlbums;In this example we assign our
success
andfail
functions as parameters of the$.ajax()
function. As stated above, thefail
function is optional.Please note: Unless stated otherwise execution of the
fail
function will cause the flow to stop and trigger theonFail
function. -
Accepts:
new Flow()
As an alternative to executing an
fn
function, we can give the task a sub-flow to execute instead. Ifflow
is defined,fn
value will be ignored.{;}{console;}{console;}var subFlow =fn: myFunction success: myFunctionSuccess;flow: subFlow success: subFlowSuccess;// Log:// Completed 1 true// Sub-flow complete! -
Accepts:
function(attributes)
A callback function that is passed as the first parameter of the
fn
function of the task. Executing it will successfully finish the task and trigger theonProgress
function, unlessnew Error()
is returned. This function is optional (if not defined, an empty function will be passed instead) and can receive any number of parameters.{;}{console;}fn: myFunction success: myFunctionSuccess;// Log:// Completed 1 true- Returning
new Error()
by the function is equal to executing thefail
function. - The
onProgress
function will receive anything returned bysuccess
.
- Returning
-
Accepts:
function(error)
A callback function that is passed as the second parameter of the
fn
function of the task. Executing it will cause the task to fail and under default conditions fail the flow and trigger theonFail
function. This function is optional. Any result returned by this function will be passed to theonFail
function.{;}{console}fn: myFunction fail: logError;// Log:// Something went wrong! -
Accepts:
boolean
Default:
false
ortrue
ifdefaultSync
options is used.When the task is set as 'sync', its execution will be delayed until all the tasks before it had completed.
{;}{;}{;}{console;}// No sync is usedfn: test1 success: logResultfn: test2 success: logResultfn: test3 success: logResult;// Log:// Test3 complete// Test2 complete// Test1 complete// The last task is defined as syncfn: test1 success: logResultfn: test2 success: logResultfn: test3 success: logResult sync: true;// Log:// Test2 complete// Test1 complete// Test3 complete -
Accepts:
integer
Default:
0
When we want to give the task a second chance to complete successfully after failing, we can use
failRetries
to define how many times we want it to retry the task. It is important to note that the number represents a number of times to retry the task after the task has failed the first time (i.e. settingfailRetries: 2
will cause the task to execute additional two times).var num = 0;{num++;if num % 3 > 0;else;}{console;}{console;}// Give the task another 2 attempts to succeedfn: myFunction success: logSuccess fail: logErrors failRetries: 2;// Log:// 1 is not divisible by 3// 2 is not divisible by 3// Great success! 3 is divisible by 3 -
Accepts:
integer
orfunction
Default:
0
Used in conjunction with
failRetries
, we can delay the execution of another retry by a defined amount of milliseconds. We can instead pass a function to dynamically modify the delay time (this function must return a number).var num = 0;{num++;if num % 3 > 0;else;}{return num * 1000;}{console;}{console;}// Dynamically set the retry intervalfn: myFunction success: logSuccess fail: logErrors failRetries: 2 retryInterval: setRetryInterval;// Log:// 1 is not divisible by 3//// (After 1000ms)// 2 is not divisible by 3//// (After 2000ms)// Great success! 3 is divisible by 3 -
Accepts:
boolean
Default:
false
Setting this as
true
will not cause a failed task to fail the entire flow. If 'failRetries' is used, the task will still attempt to perform retries.{;}{;}{;}{console;}{console;}// This flow will not be completed, failing on test2fn: test1 success: logResultfn: test2 success: logResult fail: logErrorfn: test3 success: logResult sync: true;// Log:// Test2 had failed!// This flow will be completed even though test2 is set to failfn: test1 success: logResultfn: test2 success: logResult fail: logError continueOnFail: truefn: test3 success: logResult sync: true;// Log:// Test2 had failed!// Test1 complete// Test3 complete
Options
Options is the second parameter you can provide to the Flow constructor to define general callbacks and certain behaviors of your flow.
... { console } { console; } { console; };
Option | Description | Accepts | Default |
---|---|---|---|
onComplete |
A callback function to be executed after each successful execution of the flow. | function |
N/A |
onFail |
A callback function to be executed each time the entire flow fails. If the fail function of the failed task returns a value, this value will be passed to the onFail function |
function |
N/A |
onProgress |
A callback function that will execute each time a task completes successfully. If the success function of the task returns any value except new Error() , this value will be passed to the onProgress function. |
function |
N/A |
defaultSync |
If set as true , defaultSync will cause all tasks to become sync by default. |
boolean |
false |
Methods
Methods are functions used to execute, stop or add tasks to the flow. Methods can be chained.
Method | Description | Parameters |
---|---|---|
execute() |
Starts the execution of the flow. | Accepts two optional functions for complete and fail callbacks. |
push(tasks) |
Pushes tasks to the end of the task list. | Can accept a single task object or an array of tasks. |
pushAndExecute(tasks) |
A shorthand method, equals flow.push(tasks).execute() . |
Accepts tasks as a first parameter and optional callbacks as second and third. |
stop() |
Stops the execution of the flow and prevents the execution of callbacks of currently executing tasks. | N/A |
restart() |
Restarts the execution of the flow. | Accepts two optional functions for complete and fail callbacks. |
-
Optional:
complete
andfail
callback functionsThis method starts the execution of the flow.
Please note: The optional
complete
andfail
callbacks will execute in addition to theonComplete
andonError
functions we define in the options. The main difference is thatexecute(complete, fail)
callbacks will execute only once, while the ones we set in the options will execute every time the flow completes or fails.{console;}var flow = ...{console};flow;// Log:// Done and done// Flow execution was completedPlease note: It is not advised to use
execute()
on a flow that was stopped by thestop()
method or by previously failing. This is because there is no reliable way to determine the exact stopping point in the tasks list. Useexecute()
only on flows that were completed and after pushing additional tasks, otherwise userestart()
. -
Required: a task
object
orarray
of tasksThis method is used to add additional tasks to the end of the tasks list of the flow.
var flow = ...;flow; -
Required: a task
object
orarray
of tasksOptional:
complete
andfail
callback functionsThis is a shorthand method, equals
flow.push(...).execute()
. -
This method will stop the execution of the flow and prevent any currently executing tasks from executing their callbacks.
-
Optional:
complete
andfail
callback functionsUse this method to restart the flow from the first task.
Examples
-
var loadedImages = ;{var image = ;imageonload = success;imageonerror = fail;imagesrc = imageUrl;}{loadedImages; // Push the loaded image to the loadedImages array for later use}{var tasks = ;if imageUrls && imageUrlslength// Create our tasks list by looping over the imageUrls arrayfor var i= 0 l=imageUrlslength; i<l; i++tasks;tasks{// For the sake of this example, we'll add our loaded images to the BODY elementfor var i=0 l=loadedImageslength; i<l; i++documentbody;};}// Lets load some images;
Contributors
Special tanks to Shane Goodson for helping me write this README and testing.
License
This project is licensed under the MIT License - see the LICENSE.txt file for details.