A simple library for defining and executing JavaScript task trees.
- Support for synchronous, asynchronous, and promise-based tasks.
- Automatic result passing between dependent tasks.
- Rich API for building and modifying task trees.
- Small, dependency-free, and available as both ES2015 and CommonJS libraries.
$ npm install tasker-lib
Note:
tasker-lib
requires a Promise implementation available on the global object.
Have you previously used a task-based build system? You'll feel right at home with the tasker-lib
API.
Using tasker-lib
is quick and easy:
- Create a new
TaskRunner
, optionally supplying configuration. - Add tasks through the
addTask
method. - Optionally modify the task tree by using
removeTask
,addDependencies
, andremoveDependencies
. These may only be called while tasks are not being executed. - Optionally use the dependency results with the
results
object. Each task only has access to the results of its direct dependencies. - Run a task, and all its dependencies, with the
run
method. All methods are locked during execution.
import {TaskRunner} from "tasker-lib";
const taskRunner = new TaskRunner();
// This sync task returns 1, which becomes available to tasks that depend on it through the "results" object.
taskRunner.addTask("dependency", () => 1);
taskRunner.addTask("root", ["dependency"], (results) => {
const dependencyResult = results["dependency"];
console.log(`Result of "dependency" is: ${dependencyResult}`); // 1
return dependencyResult + 1;
});
taskRunner.run("root").then((finalResult) => {
console.log(`Final results are ${finalResult}`); // finalResult === 2
});
// The dependency list is optional for tasks that have no dependencies.
taskRunner.addTask("promise-task", (results) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("some-async-result");
}, 1000);
});
});
taskRunner.addTask("async-task", (results, done) => {
setTimeout(() => {
done("some-async-result");
}, 1000);
});
Dependencies can be added or removed to any task that has already been added. Calling addDependency
multiple times with
the same taskName and dependencies will be ignored after the first call.
taskRunner.addTask("root", () => 3);
// Dependencies may be added before they exist, but the parent task must exist at this point.
taskRunner.addDependencies("root", ["child1"]);
taskRunner.addTask("child1", () => 1);
taskRunner.addTask("child2", () => 2);
taskRunner.addDependencies("child1", "child2"); // A string may be used for sole dependencies.
taskRunner.removeDependencies("root", "child1"); // child2 is still a dependency of child1, but not of root.
const options = {
throwOnOverwrite: false // defaults to true
};
const taskRunner = new TaskRunner(options);
taskRunner.addTask("root", () => 1);
taskRunner.addTask("root", () => 1); // This would throw if throwOnOverwrite is true.
Before each task starts, onTaskStart
will be called with the task name and dependency list. Then, if there are any
dependencies, they will be executed and onTaskStart
will likewise be called with their name and dependency list.
onTaskEnd
will be called with the task name once the task has completed.
onTaskCancel
will be called with the task name if a dependent task prevented it from executing.
onTaskFail
will be called with the task name if an error occurred during task execution.
const options = {
onTaskStart: (taskName, taskDependencies) => {
console.log(`Task started: '${taskName}'. Depends on ${taskDependencies}.`);
},
onTaskEnd: (taskName) => {
console.log(`Task ended: '${taskName}'`);
}
};
const taskRunner = new TaskRunner(options);
taskRunner.addTask("child1", () => 1);
taskRunner.addTask("root", ["child1"], () => console.log(" - Running! - "));
taskRunner.run("root");
// Task started: 'root'. Depends on [].
// - Running! -
// Task ended: 'root'
For command line usage, see tasker-cli.
tasker-lib
uses SemVer for versioning. All releases will be available on both GitHub and npm.
MIT