Socket
Socket
Sign inDemoInstall

taskgroup

Package Overview
Dependencies
Maintainers
1
Versions
135
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

taskgroup - npm Package Compare versions

Comparing version 2.0.0 to 3.0.0

example.js

496

out/lib/taskgroup.js
// Generated by CoffeeScript 1.6.2
var TaskGroup, ambi, typeChecker,
var EventEmitter, Task, TaskGroup, ambi,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice;
typeChecker = require('typechecker');
ambi = require('ambi');
TaskGroup = (function() {
_Class.prototype.total = 0;
EventEmitter = require('eventemitter2').EventEmitter2;
_Class.prototype.completed = 0;
Task = (function(_super) {
__extends(Task, _super);
_Class.prototype.running = 0;
Task.prototype.type = 'task';
_Class.prototype.exited = false;
Task.prototype.completed = false;
_Class.prototype.breakOnError = true;
Task.prototype.parent = null;
_Class.prototype.autoClear = false;
Task.prototype.name = null;
_Class.prototype.queue = [];
Task.prototype.fn = null;
_Class.prototype.mode = 'parallel';
function Task() {
var args, fn, name;
_Class.prototype.lastResult = null;
_Class.prototype.results = [];
_Class.prototype.errors = [];
_Class.prototype.next = function() {
throw new Error('Groups require a completion callback');
};
function _Class() {
var arg, args, autoClear, breakOnError, mode, next, _i, _len;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
this.clear();
for (_i = 0, _len = args.length; _i < _len; _i++) {
arg = args[_i];
if (typeChecker.isString(arg)) {
if (arg === 'serial' || arg === 'sync') {
this.mode = 'serial';
}
} else if (typeChecker.isFunction(arg)) {
this.next = arg;
} else if (typeChecker.isObject(arg)) {
next = arg.next, mode = arg.mode, breakOnError = arg.breakOnError, autoClear = arg.autoClear;
if (next) {
this.next = next;
}
if (mode) {
this.mode = mode;
}
if (breakOnError) {
this.breakOnError = breakOnError;
}
if (autoClear) {
this.autoClear = autoClear;
}
} else {
throw new Error('Unknown argument sent to Groups constructor');
this.setConfig = __bind(this.setConfig, this);
Task.__super__.constructor.apply(this, arguments);
name = fn = null;
if (args.length) {
if (args.length === 2) {
name = args[0], fn = args[1];
} else if (args.length === 1) {
fn = args[0];
}
}
this.setConfig({
name: name,
fn: fn
});
this;
}
_Class.prototype.clear = function() {
this.total = 0;
this.completed = 0;
this.running = 0;
this.exited = false;
this.queue = [];
this.results = [];
this.errors = [];
this.lastResult = null;
Task.prototype.setConfig = function(opts) {
var key, value;
if (opts == null) {
opts = {};
}
for (key in opts) {
if (!__hasProp.call(opts, key)) continue;
value = opts[key];
this[key] = value;
}
return this;
};
_Class.prototype.hasTasks = function() {
return this.queue.length !== 0;
};
Task.prototype.run = function() {
var complete,
_this = this;
_Class.prototype.hasCompleted = function() {
return this.total !== 0 && this.total === this.completed;
};
complete = function() {
var args;
_Class.prototype.isRunning = function() {
return this.running !== 0;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
_this.completed = true;
return _this.emit.apply(_this, ['complete'].concat(__slice.call(args)));
};
this.emit('run');
process.nextTick(function() {
return ambi(_this.fn.bind(_this), complete);
});
return this;
};
_Class.prototype.hasExited = function(value) {
if (value != null) {
this.exited = value;
}
return this.exited === true;
};
return Task;
_Class.prototype.logError = function(err) {
if (this.errors[this.errors.length - 1] !== err) {
this.errors.push(err);
}
return this;
};
})(EventEmitter);
_Class.prototype.complete = function() {
var args, err;
TaskGroup = (function(_super) {
__extends(TaskGroup, _super);
TaskGroup.prototype.type = 'taskgroup';
TaskGroup.prototype.running = 0;
TaskGroup.prototype.remaining = null;
TaskGroup.prototype.err = null;
TaskGroup.prototype.results = null;
TaskGroup.prototype.parent = null;
TaskGroup.prototype.paused = true;
TaskGroup.prototype.name = null;
TaskGroup.prototype.fn = null;
TaskGroup.prototype.concurrency = 1;
TaskGroup.prototype.pauseOnError = true;
function TaskGroup() {
var args, fn, name,
_this = this;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
err = args[0] || void 0;
this.lastResult = args;
if (err) {
this.logError(err);
this.run = __bind(this.run, this);
this.pause = __bind(this.pause, this);
this.stop = __bind(this.stop, this);
this.clear = __bind(this.clear, this);
this.complete = __bind(this.complete, this);
this.nextItem = __bind(this.nextItem, this);
this.nextItems = __bind(this.nextItems, this);
this.isReady = __bind(this.isReady, this);
this.hasItems = __bind(this.hasItems, this);
this.addGroup = __bind(this.addGroup, this);
this.createGroup = __bind(this.createGroup, this);
this.addTask = __bind(this.addTask, this);
this.createTask = __bind(this.createTask, this);
this.addItem = __bind(this.addItem, this);
this.setConfig = __bind(this.setConfig, this);
TaskGroup.__super__.constructor.apply(this, arguments);
this.err = null;
this.results = [];
this.remaining = [];
name = fn = null;
if (args.length) {
if (args.length === 2) {
name = args[0], fn = args[1];
} else if (args.length === 1) {
fn = args[0];
}
}
this.results.push(args);
if (this.running !== 0) {
--this.running;
}
if (this.hasExited()) {
this.setConfig({
name: name,
fn: fn
});
this.on('run', function() {
var _ref;
} else {
if (err && this.breakOnError) {
this.exit();
} else {
++this.completed;
if (this.hasTasks()) {
this.nextTask();
} else if (this.isRunning() === false && this.hasCompleted()) {
this.exit();
}
return (_ref = _this.fn) != null ? _ref.call(_this, _this.addGroup, _this.addTask) : void 0;
});
process.nextTick(function() {
if (_this.fn && !_this.parent) {
return _this.run();
}
});
this.on('item.complete', function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
_this.results.push(args);
if (args[0]) {
_this.err = args[0];
}
--_this.running;
if (_this.paused) {
return;
}
if (!_this.complete()) {
return _this.nextItems();
}
});
this;
}
TaskGroup.prototype.setConfig = function(opts) {
var key, value;
if (opts == null) {
opts = {};
}
for (key in opts) {
if (!__hasProp.call(opts, key)) continue;
value = opts[key];
this[key] = value;
}
return this;
};
_Class.prototype.completer = function() {
var _this = this;
TaskGroup.prototype.addItem = function(item) {
var me;
return function() {
me = this;
item.onAny(function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return _this.complete.apply(_this, args);
};
return me.emit.apply(me, ["item." + this.event].concat(__slice.call(args)));
});
this.emit('add', item);
this.remaining.push(item);
if (!this.paused) {
this.nextItems();
}
return item;
};
_Class.prototype.exit = function(err) {
var errors, lastResult, results;
TaskGroup.prototype.createTask = function() {
var args, task;
if (err == null) {
err = null;
}
if (err) {
this.logError(err);
}
if (this.hasExited()) {
} else {
lastResult = this.lastResult;
results = this.results;
if (this.errors.length === 0) {
errors = null;
} else if (this.errors.length === 1) {
errors = this.errors[0];
} else {
errors = this.errors;
}
if (this.autoClear) {
this.clear();
} else {
this.hasExited(true);
}
this.next(errors, lastResult, results);
}
return this;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
task = (function(func, args, ctor) {
ctor.prototype = func.prototype;
var child = new ctor, result = func.apply(child, args);
return Object(result) === result ? result : child;
})(Task, args, function(){});
return task;
};
_Class.prototype.tasks = function(tasks) {
var task, _i, _len;
TaskGroup.prototype.addTask = function() {
var args, me, task;
for (_i = 0, _len = tasks.length; _i < _len; _i++) {
task = tasks[_i];
this.push(task);
}
return this;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
me = this;
task = this.createTask.apply(this, args).setConfig({
parent: this
});
task.onAny(function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return me.emit.apply(me, ["task." + this.event].concat(__slice.call(args)));
});
return this.addItem(task);
};
_Class.prototype.push = function() {
var args;
TaskGroup.prototype.createGroup = function() {
var args, group;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
++this.total;
this.queue.push(args);
return this;
group = (function(func, args, ctor) {
ctor.prototype = func.prototype;
var child = new ctor, result = func.apply(child, args);
return Object(result) === result ? result : child;
})(TaskGroup, args, function(){});
return group;
};
_Class.prototype.pushAndRun = function() {
var args;
TaskGroup.prototype.addGroup = function() {
var args, group, me;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
if (this.mode === 'serial' && this.isRunning()) {
this.push.apply(this, args);
} else {
++this.total;
this.runTask(args);
}
return this;
me = this;
group = this.createGroup.apply(this, args).setConfig({
concurrency: this.concurrency,
parent: this
});
group.onAny(function() {
var args;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
return me.emit.apply(me, ["group." + this.event].concat(__slice.call(args)));
});
return this.addItem(group);
};
_Class.prototype.nextTask = function() {
var task;
TaskGroup.prototype.hasItems = function() {
return this.remaining.length !== 0;
};
if (this.hasTasks()) {
task = this.queue.shift();
this.runTask(task);
}
return this;
TaskGroup.prototype.isReady = function() {
return !this.concurrency || this.running < this.concurrency;
};
_Class.prototype.runTask = function(task) {
var err, me, run;
TaskGroup.prototype.nextItems = function() {
var item, items;
me = this;
try {
run = function() {
var complete, _task;
++me.running;
complete = me.completer();
if (typeChecker.isArray(task)) {
if (task.length === 2) {
_task = task[1].bind(task[0]);
} else if (task.length === 1) {
_task = task[0];
} else {
throw new Error('an invalid task was pushed');
}
} else {
_task = task;
}
return ambi(_task, complete);
};
if (this.completed !== 0 && (this.mode === 'parallel' || (this.completed % 100) === 0)) {
setTimeout(run, 0);
items = [];
while (true) {
item = this.nextItem();
if (item) {
items.push(item);
} else {
run();
break;
}
} catch (_error) {
err = _error;
this.complete(err);
}
return this;
if (items.length) {
return items;
} else {
return false;
}
};
_Class.prototype.run = function(mode) {
var task, _i, _len, _ref, _ref1;
TaskGroup.prototype.nextItem = function() {
var nextItem;
if (this.isRunning() === false) {
if (mode) {
this.mode = mode;
if (this.hasItems()) {
if (this.isReady()) {
nextItem = this.remaining.shift();
++this.running;
nextItem.run();
return nextItem;
}
this.hasExited(false);
if (this.hasTasks()) {
if ((_ref = this.mode) === 'serial' || _ref === 'sync') {
this.nextTask();
} else {
_ref1 = this.queue;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
task = _ref1[_i];
this.nextTask();
}
}
} else {
this.exit();
}
return false;
};
TaskGroup.prototype.complete = function() {
var completed, empty, pause;
pause = this.pauseOnError && this.err;
empty = this.hasItems() === false && this.running === 0;
completed = pause || empty;
if (completed) {
if (pause) {
this.pause();
}
this.emit('complete', this.err, this.results);
this.err = null;
this.results = [];
}
return this;
return completed;
};
_Class.prototype.async = function() {
return this.parallel();
TaskGroup.prototype.clear = function() {
this.remaining.splice(0);
return this;
};
_Class.prototype.parallel = function() {
this.run('parallel');
TaskGroup.prototype.stop = function() {
this.pause();
this.clear();
return this;
};
_Class.prototype.sync = function() {
return this.serial();
TaskGroup.prototype.pause = function() {
this.paused = true;
return this;
};
_Class.prototype.serial = function() {
this.run('serial');
TaskGroup.prototype.run = function() {
var args,
_this = this;
args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
this.paused = false;
this.emit('run');
process.nextTick(function() {
if (!_this.complete()) {
return _this.nextItems();
}
});
return this;
};
return _Class;
return TaskGroup;
})();
})(EventEmitter);
module.exports = TaskGroup;
module.exports = {
Task: Task,
TaskGroup: TaskGroup
};
{
"name": "taskgroup",
"version": "2.0.0",
"description": "Group together synchronous and asynchronous tasks and execute them in either serial or parallel",
"version": "3.0.0",
"description": "Group together synchronous and asynchronous tasks and execute them with support for concurrency, naming, and nesting.",
"homepage": "https://github.com/bevry/taskgroup",

@@ -12,3 +12,4 @@ "keywords": [

"tasks",
"batch"
"batch",
"concurrency"
],

@@ -33,8 +34,9 @@ "author": "Bevry Pty Ltd <us@bevry.me> (http://bevry.me)",

"dependencies": {
"typechecker": "~2.0.1",
"ambi": "~2.0.0"
"ambi": "~2.0.0",
"eventemitter2": "~0.4.11"
},
"devDependencies": {
"coffee-script": "~1.6.2",
"joe": "~1.1.2"
"joe": "~1.1.2",
"chai": "~1.5.0"
},

@@ -45,5 +47,5 @@ "directories": {

"scripts": {
"test": "node ./out/test/taskgroup-test.js --joe-reporter=list"
"test": "node ./out/test/taskgroup-test.js"
},
"main": "./out/lib/taskgroup.js"
}

@@ -1,6 +0,10 @@

# Task Group [![Build Status](https://secure.travis-ci.org/bevry/taskgroup.png?branch=master)](http://travis-ci.org/bevry/taskgroup)
Group together synchronous and asynchronous tasks and execute them in either serial or parallel
# Task Group
[![Build Status](https://secure.travis-ci.org/bevry/taskgroup.png?branch=master)](http://travis-ci.org/bevry/taskgroup)
[![NPM version](https://badge.fury.io/js/taskgroup.png)](https://npmjs.org/package/taskgroup)
Group together synchronous and asynchronous tasks and execute them with support for concurrency, naming, and nesting.
## Install

@@ -21,24 +25,120 @@

``` coffeescript
# Import
TaskGroup = require('taskgroup')
### Example
# Add tasks to the group and fire them in parallel
tasks = new TaskGroup (err,lastResult,results) -> console.log(err,lastResult,results)
tasks.push (complete) ->
someAsyncFunction(arg1, arg2, complete)
tasks.push ->
someSyncFunction(arg1, arg2)
tasks.run() # can also use tasks.run('parallel')
``` javascript
// Import
var TaskGroup = require('taskgroup').TaskGroup;
# Add tasks to the group and fire them in serial
tasks = new TaskGroup (err,lastResult,results) -> console.log(err,lastResult,results)
tasks.push (complete) ->
someAsyncFunction(arg1, arg2, complete)
tasks.push ->
someSyncFunction(arg1, arg2)
tasks.run('serial')
// Create our new group
var group = new TaskGroup();
// Define what should happen once the group has completed
group.once('complete', function(err,results){
// Log the error that has occured
console.log(err);
// => null
// Log the results that our group received from the executing items
console.log(JSON.stringify(results));
/* =>
[
[null, 'first', 'task'],
[null, 'second task'],
[null, [
[null, 'sub second task'],
[null, 'sub first', 'task']
]]
]
*/
});
// Add an asynchronous task that gives the result to the completion callback
group.addTask(function(complete){
setTimeout(function(){
complete(null, 'first', 'task');
},500);
});
// Add a synchronous task that returns the result
// Errors should be returned, though if an error is thrown we will catch it
group.addTask(function(){
return 'second task';
});
// Add a sub-group to our exiting group
group.addGroup(function(addGroup,addTask){
// Tell this sub-group to execute in parallel (all at once) by setting its concurrency to unlimited
// by default the concurrency for all groups is set to 1
// which means that they execute in serial fashion (one after the other, instead of all at once)
this.setConfig({concurrency:0});
// Add an asynchronous task that gives its result to the completion callback
addTask(function(complete){
setTimeout(function(){
complete(null, 'sub first', 'task');
},500);
});
// Add a synchronous task that returns its result
addTask(function(){
return 'sub second task';
});
});
// Execute our group
group.run();
```
### TaskGroup API
``` javascript
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 configuration
- `setConfig(config)` - set the configuration for the group, returns chain
- `addTask(args...)` - create a new task item with the arguments and adds it to the group, returns the new task item
- `addGroup(args...)` - create a new group item with the arguments and adds it to the group, returns the new group item
- `clear()` - remove the remaining items to be executed
- `stop()` - clear and pause
- `pause()` - pause the execution of the items
- `run()` - start/resume executing the items, returns chain
- All those of [EventEmitter2](https://github.com/hij1nx/EventEmitter2)
- Available configuration:
- `name`, no default - allows us to assign a name to the group, useful for debugging
- `fn(addGroup,addTask)`, no default - allows us to use an inline and self-executing style for defining groups, useful for nesting
- `concurrency`, defaults to `1` - how many items shall we allow to be run at the same time, set to `0` to allow unlimited
- `pauseOnError`, 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 items
- `complete(err, results)` - fired when all our items have completed
- `task.run()` - fired just before a task item executes
- `task.complete(err, args...)` - fired when a task item has completed
- `group.run()` - fired just before a group item executes
- `group.complete(err, results)` - fired when a group item has completed
- `item.run()` - fired just before an item executes (fired for both sub-tasks and sub-groups)
- `item.complete(err, args...)` - fired when an item has completed (fired for both sub-task and sub-groups)
### Task API
``` javascript
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 configuration
- `setConfig(config)` - set the configuration for the group, returns chain
- `run()` - execute the task
- Available configuration:
- `name`, no default - allows us to assign a name to the group, useful for debugging
- `fn(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 provided
- Available events:
- `run()` - fired just before we execute the task
- `complete(err, args...)` - fired when the task has completed
## History

@@ -45,0 +145,0 @@ You can discover the history inside the [History.md](https://github.com/bevry/taskgroup/blob/master/History.md#files) file

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc