TaskGroup
Group together synchronous and asynchronous tasks and execute them with support for concurrency, naming, and nesting.
Install
- Use:
require('taskgroup')
- Install:
npm install --save taskgroup
- Use:
require('taskgroup')
- Install:
ender add taskgroup
- Use:
require('taskgroup')
- Install:
component install bevry/taskgroup
- Use:
require('taskgroup')
- Install:
bower install taskgroup
Usage
Example
var TaskGroup = require('taskgroup').TaskGroup;
var group = new TaskGroup();
group.once('complete', function(err,results){
console.log(err);
console.log(JSON.stringify(results));
});
group.addTask(function(complete){
setTimeout(function(){
complete(null, 'first', 'task');
},500);
});
group.addTask(function(){
return 'second task';
});
group.addGroup(function(addGroup,addTask){
this.setConfig({concurrency:0});
addTask(function(complete){
setTimeout(function(){
complete(null, 'sub first', 'task');
},500);
});
addTask(function(){
return 'sub second task';
});
});
group.run();
TaskGroup API
new (require('taskgroup')).TaskGroup()
- Available methods:
constructor(name?,fn?)
- create our new group, the arguments name
and fn
are optional, refer to their entries in configurationsetConfig(config)
- set the configuration for the group, returns chainaddTask(args...)
- create a new task item with the arguments and adds it to the group, returns the new task itemaddGroup(args...)
- create a new group item with the arguments and adds it to the group, returns the new group itemgetTotals()
- returns counts for the following {running,remaining,completed,total}
clear()
- remove the remaining items to be executedpause()
- pause the execution of the itemsstop()
- clear and pauseexit(err)
- stop and complete, err
if specified is sent to the completion event when firedcomplete()
- will fire the completion event if we are already complete, useful if you're binding your listeners after runrun()
- start/resume executing the items, returns chain- All those of EventEmitter2
- Available configuration:
name
, no default - allows us to assign a name to the group, useful for debuggingfn(addGroup,addTask,complete?)
, no default - allows us to use an inline and self-executing style for defining groups, useful for nestingconcurrency
, defaults to 1
- how many items shall we allow to be run at the same time, set to 0
to allow unlimitedpauseOnError
, defaults to true
- if an error occurs in one of our items, should we stop executing any remaining items?
- setting to
false
will continue with execution with the other items even if an item experiences an error
- Available events:
run()
- fired just before we execute the itemscomplete(err, results)
- fired when all our items have completedtask.run(task)
- fired just before a task item executestask.complete(task, err, args...)
- fired when a task item has completedgroup.run(group)
- fired just before a group item executesgroup.complete(group, err, results)
- fired when a group item has completeditem.run(item)
- fired just before an item executes (fired for both sub-tasks and sub-groups)item.complete(item, err, args...)
- fired when an item has completed (fired for both sub-task and sub-groups)
Task API
new (require('taskgroup')).Task()
- Available methods:
constructor(name?,fn?)
- create our new task, the arguments name
and fn
are optional though fn
must be set at some point, refer to their entries in configurationsetConfig(config)
- set the configuration for the group, returns chaincomplete()
- will fire the completion event if we are already complete, useful if you're binding your listeners after runrun()
- execute the task
- Available configuration:
name
, no default - allows us to assign a name to the group, useful for debuggingfn(complete?)
, no default - must be set at some point, it is the function to execute for the task, if it is asynchronous it should use the completion callback providedargs
, no default - an array of arguments that you would like to precede the completion callback when executing fn
- Available events:
run()
- fired just before we execute the taskcomplete(err, args...)
- fired when the task has completed
The biggest advantage and difference of TaskGroup over async.js is that TaskGroup has one uniform API to rule them all, whereas with async.js I found that I was always having to keep referring to the async manual to try and figure out which is the right call for my use case then somehow wrap my head around the async.js way of doing things (which more often than not I couldn't), whereas with TaskGroup I never have that problem as it is one consistent API for all the different use cases.
Let's take a look at what the most common async.js methods would look like in TaskGroup:
async.series([
function(){},
function(callback){callback();}
], next);
new TaskGroup().once('complete', next)
.addTask(function(){})
.addTask(function(callback){callback();})
.run();
async.parallel([
function(){},
function(callback){callback();}
], next);
new TaskGroup().setConfig({concurrency:0}).once('complete', next)
.addTask(function(){})
.addTask(function(callback){callback();})
.run();
async.map(['file1','file2','file3'], fs.stat, next);
var tasks = new TaskGroup().setConfig({concurrency:0}).once('complete', next);
['file1','file2','file3'].forEach(function(file){
tasks.addTask(function(complete){
fs.stat(file,complete);
});
});
tasks.run();
Another big advantage of TaskGroup over async.js is TaskGroup's ability to add tasks to the group once execution has already started - this is a common use case when creating an application that must perform it's actions serially, so using TaskGroup you can create a serial TaskGroup for the application, run it right away, then add the actions to the group as tasks.
A final big advantage of TaskGroup over async.js is TaskGroup's ability to do nested groups, this allowed us to created the Joe Testing Framework & Runner incredibly easily, and because of this functionality Joe will always know which test (task) is associated to which suite (task group), whereas test runners like mocha have to guess (they add the task to the last group, which may not always be the case! especially with dynamically created tests!).
History
You can discover the history inside the History.md file
License
Licensed under the incredibly permissive MIT License
Copyright © 2013+ Bevry Pty Ltd
Copyright © 2011-2012 Benjamin Arthur Lupton