Links: Index
Async is a set of methods that lets you execute an array of operations in asynchronous mode. It implements following methods:
async.flow( operations, callback[,timeout] )
async.waterfall( operations, callback[,parallel, timeout] )
async.map( operations, ev, callback[,timeout] )
async.waterfall.map( operations, ev, callback[,parallel, timeout] )
async.filter( operations, ev, callback[,timeout] )
async.waterfall.filter( operations, ev, callback[,parallel, timeout] )
async.forEach( operations, ev, callback[,timeout] )
async.waterfall.forEach( operations, ev, callback[,parallel, timeout] )Note:
ev - evaluation function, this function is called at every iteration through operations.
Methods with waterfall are implemented to execute operations in parallel or many at a time, the rest will execute one at a time.
When any method finishes it's job, it returns an AsyncApp object:
{
index : function () { ... }
recieve : function (id, args) { ... }
wait : function () { ... }
reserve : function () { ... }
run : function (fun, args, context) { ... }
flush : function ([,fun, args]) { ... }
processing : function () {
// returns number of actions that are not yet processed
}
responses : function (returnAsArrayOfValues) {
// if returnAsArrayOfValues === true than function returns an array of values
//
// in other case it returns an object with following structure
// {
// operation_id1: arguments,
// operation_id2: arguments,
// operation_id3: arguments,
// operation_id4: arguments
// ...
// }
}
errors : function () {
// returns list of errors
}
done : function (cb) {
// similar with a Promise, it will execute "cb" function after flow was finished
}
}They are used internally to control flow of execution. The object is returned in function context and is accessed with keyword this.
Example:
this.processing()An important part of these functions is the first function argument - operations. It is an array of arrays (but not necessarily). Each nested array has following structure:
[
[
function (a, b, cb) {
/* operation function */ cb();
},
[2, 3, null] /* ( optional ) operation arguments */
context, /* ( optional ) */
2 // callbackIndex
],
[
function (a, b, cb) {
/* operation function */ cb();
},
[2, 3, null] /* ( optional ) operation arguments */
context, /* ( optional ) */
2 // callbackIndex, ( optional )
],
[ ... ]
]In your frontend include following scripts:
<script type="text/javascript" charset="utf-8" src="ApplicationPrototype.js"></script>
<script type="text/javascript" charset="utf-8" src="ApplicationBuilder.js"></script>and then call:
var App = new ApplicationBuilder(); // it will initialize bare-bone application prototype
App.require('async').then(function (Async) { // require async module.
App.bind('async', function () { // binds a function to App object.
return Async;
});
}, function (err) {
console.error(err);
})
//you may access async module via: App.async()also we will include following functions for testing purposes:
// testing array for filter methods
var unfiltered = [1, '1', 2, [], 'sun', {}, 3];
// simulates some time consuming work
var timedFunction = function (next) {
console.log("started: " + new Date().valueOf());
setTimeout(function () {
var t = new Date().valueOf();
console.log("ended: " + t);
next(t + "");
}, 2000);
};There are 2 execution implementations: flow and waterfall
flow- executes one operation at a time. When it finishes, it will start next one.waterfall- executes operations in parallel. It will start a number (Default 27) of executions at the same time. If one finishes before the rest, it will start another one. This will ensure that at all the times there are a constant number of parallel executions active.
Note: Current implementation of waterfall waits for first operation to execute, and then fires next operations asynchronously.
async.flow - executes all operations in synchronous way, one after another. You may set a timeout before next function call as last argument.
Example:
// function used for testing, its returns solve after 2 secconds
// simulates some time consuming work
var timedFunction = function (next) {
console.log("started: " + new Date().valueOf());
setTimeout(function () {
var t = new Date().valueOf();
console.log("ended: " + t);
next(t + "");
}, 2000);
};
App.async().flow(
[[timedFunction], [timedFunction], [timedFunction], [timedFunction]],
function (data) {
console.log('final callback, data : ', data);
}
);Output:
started: 1498058741615
ended: 1498058743620
started: 1498058743623
ended: 1498058745624
started: 1498058745630
ended: 1498058747631
started: 1498058747636
ended: 1498058749638
final callback, data : undefinedFinal callback does not carry any data with it, it just signals end of the execution. This example will execute every operation with an interval of 2 seconds.
async.waterfall - executes all operations in an asynchronous way, many at a time. Same as flow, it wont return anything, it will callback to signal the end of execution.
Example:
// function used for testing, its returns solve after 2 secconds
// simulates some time consuming work
var timedFunction = function (next) {
console.log("started: " + new Date().valueOf());
setTimeout(function () {
var t = new Date().valueOf();
console.log("ended: " + t);
next(t + "");
}, 2000);
};
//we will generate an array of arrays of functions that will print a number after a random period of time.
App.async().waterfall(
[[timedFunction], [timedFunction], [timedFunction], [timedFunction]],
function (data) {
console.log('final callback, data : ', data);
}
);Output:
started: 1498058854354
ended: 1498058856355
started: 1498058856358
started: 1498058856359
started: 1498058856360
ended: 1498058858360
ended: 1498058858361
ended: 1498058858362
final callback, data : undefined
async.waterfall finishedasync.map - iterates through operations in synchronous way one at a time. Final callback returns an array with results.
async.waterfall.map - works the same as async.map
Example:
// function used for testing, its returns solve after 2 secconds
// simulates some time consuming work
var timedFunction = function (next) {
console.log("started: " + new Date().valueOf());
setTimeout(function () {
var t = new Date().valueOf();
console.log("ended: " + t);
next(t + "");
}, 2000);
};
App.async().map(
[[timedFunction], [timedFunction], [timedFunction], [timedFunction]],
function (next, op, i, arr) {
op[0](next);
}, function (data) {
console.log('final callback, data : ', data);
}
);Output:
started: 1498059138534
ended: 1498059140534
started: 1498059140538
ended: 1498059142539
started: 1498059142544
ended: 1498059144545
started: 1498059144551
ended: 1498059146552
final callback, data : ["1498059140534", "1498059142539", "1498059144545", "1498059146552"]This function iterates initial array and calls callback function provided. next function will return and save the value to the final result. (similar to Array.prototype.map logic, but it is passed in callback instead of return).
async.filter - filters operations array one at a time based on value true/false sent in callback function. Same logic as Array prototype filter. Function next takes true or false as first parameter.
Example:
App.async().filter(
unfiltered,
function (next, op, i, arr) {
console.log("started: " + new Date().valueOf());
setTimeout(function () {
console.log("ended: " + new Date().valueOf());
next(typeof(op) === 'number' ? true : false);
}, 2000);
}, function (data) {
console.log('final callback, data : ', data);
}
);Output:
started: 1498059382895
ended: 1498059384896
started: 1498059384899
ended: 1498059386900
started: 1498059386905
ended: 1498059388907
started: 1498059388913
ended: 1498059390914
started: 1498059390919
ended: 1498059392921
started: 1498059392927
ended: 1498059394928
started: 1498059394934
ended: 1498059396935
final callback, data : [1, 2, 3]async.waterfall.filter - filters operations array asynchronously, Default 27 at a time. Function next takes true or false as first parameter.
Example:
App.async().waterfall.filter(
unfiltered,
function (next, op, i, arr) {
console.log("started: " + new Date().valueOf());
setTimeout(function () {
console.log("ended: " + new Date().valueOf());
next(typeof(op) === 'number' ? true : false);
}, 2000);
}, function (data) {
console.log('final callback, data : ', data);
}
);Output:
started: 1498059635682
ended: 1498059638584
started: 1498059638590
started: 1498059638591
started: 1498059638593
started: 1498059638594
started: 1498059638597
started: 1498059638599
ended: 1498059640592
ended: 1498059640593
ended: 1498059640594
ended: 1498059640597
ended: 1498059640599
ended: 1498059640600
final callback, data : [1, 2, 3]async.forEach - iterates synchronously through each of operations. Returns initial array of operations in final callback.
Example:
// function used for testing, its returns solve after 2 secconds
// simulates some time consuming work
var timedFunction = function (next) {
console.log("started: " + new Date().valueOf());
setTimeout(function () {
var t = new Date().valueOf();
console.log("ended: " + t);
next(t + "");
}, 2000);
};
App.async().forEach(
[[timedFunction], [timedFunction], [timedFunction], [timedFunction]],
function (next, op, i, arr) {
op[0](next);
}, function (data) {
console.log('final callback, data : ', data);
}
);Output:
started: 1498059819830
ended: 1498059821831
started: 1498059821834
ended: 1498059823835
started: 1498059823840
ended: 1498059825840
started: 1498059825846
ended: 1498059827847
final callback, data : [Array(1), Array(1), Array(1), Array(1)]async.waterfall.forEach - iterates asynchronously through operations.
Example:
// function used for testing, its returns solve after 2 secconds
// simulates some time consuming work
var timedFunction = function (next) {
console.log("started: " + new Date().valueOf());
setTimeout(function () {
var t = new Date().valueOf();
console.log("ended: " + t);
next(t + "");
}, 2000);
};
App.async().waterfall.forEach(
[[timedFunction], [timedFunction], [timedFunction], [timedFunction]],
function (next, op, i, arr) {
op[0](next);
}, function (data) {
console.log('final callback, data : ', data);
}
);Output:
started: 1498059973043
ended: 1498059975043
started: 1498059975047
started: 1498059975048
started: 1498059975049
ended: 1498059977048
ended: 1498059977049
ended: 1498059977050
final callback, data : [Array(1), Array(1), Array(1), Array(1)]