Noncommital Premarital Mischief
Miss any of our Open RFC calls?Watch the recordings here! »

jobify

1.0.0 • Public • Published

Jobify

RequireJS like asynchronous task runner with task dependencies.

Install

npm install jobify --save

Usage

var Jobify = require('jobify');

A very basic use case.

Jobify()
.task('foo', function(task)
{
    task.resolve('World');
})
.task('bar', ['foo'], function(task, foo)
{
    if (foo === 'World') {
        task.resolve('Hello ' + foo + '!');
    } else {
        task.reject('Expected World');
    }
})
.done(function(err, values)
{
    if (err instanceof Error) {
        console.error(err.message); // "Expected World"
    } else {
        console.log(values.bar); // "Hello World!"
    }
});

Starting The Job

None of the tasks are run until done is called. Done does not execute the tasks immediately though. It is guaranteed to be asynchronous. Because it is asynchronous, you can also call .done() first and then synchronously add tasks.

Return Value

A task callback doesn't have to be asynchronous. You can return a task value instead of calling task.resolve().

Jobify()
.task('foo', function(task)
{
    return 'World';
})
.task('bar', ['foo'], function(task, foo)
{
    return 'Hello ' + foo + '!';
})
.done(function(err, values)
{
    console.log(values.bar); // "Hello World!"
});

Duplicate Names

You can define multiple tasks with the same name. The task is not considered resolved until all of the callbacks are resolved. The resolved task value will be an array of all resolution values, in the order of callback registration.

Jobify()
.task('foo', function(task)
{
    setTimeout(function()
    {
        task.resolve('Hello');
    }, 1000);
})
.task('foo', function(task)
{
    setTimeout(function()
    {
        task.resolve('World!');
    }, 500);
})
.done(function(err, values)
{
    console.log(values.foo.join(" ")); // "Hello World!"
});

Errors

If you throw an error or call task.reject(), then the job stops immediately and no further tasks will be run. Any task that is running in parallel with a rejected task will finish, but its resolution/rejection will be ignored.

Anything thrown or passed to task.reject() will be normalized to an Error instance. A non-Error value will be used as the error message of a newly constructed Error instance.

Jobify()
.task('foo-parallel', function(task)
{
    setTimeout(function()
    {
        // I will run but...
        task.resolve('... this value will be ignored');
    }, 0);
})
.task('foo', function(task)
{
    task.reject("Oh no!");
})
.task('bar', ['foo'], function(task, foo)
{
    // This task is never run.
})
.done(function(err, values)
{
    if (err instanceof Error) {
        console.log(err.message); // "Oh no!"
    }
});

Throwing an exception synchronously is the same as calling task.reject().

Jobify()
.task('foo', function(task)
{
    throw new Error("Oh no!");
})
.task('bar', ['foo'], function(task, foo)
{
    // This task is never run.
})
.done(function(err, values)
{
    if (err instanceof Error) {
        console.log(err.message); // "Oh no!"
    }
});

API

Class Jobify

Jobify()
new Jobify()

Constructs a new Jobify instance.

.task(name, taskCallback)
.task(name, dependencies, taskCallback)

  • name is required and must be a string.
  • dependencies is an optional array of task names.
  • taskCallback is required and must be a function.
  • returns the Jobify instance for method chaining.

Runs taskCallback when all dependencies have been met.

taskCallback(task, ...)
  • task is a Task instance.
  • ... is zero or more arguments of any type.

Resolved task values matching the task's dependencies will be passed in order starting after the task argument.

.done()
.done(doneCallback)

  • doneCallback is an optional function to be called when all tasks have been resolved or if a task is rejected.
  • returns the Jobify instance for method chaining.

Begins running tasks. No tasks are run until .done() has been called at least once.

doneCallback(err, values)
  • err an Error instance or null.
  • values an object.

The err argument will either be an Error instance if any tasks were rejected, or null.

The values argument is a map of all resolved task values.

.copy()

  • returns a new Jobify instance.

Create's a copy of the Jobify instance which defines the same tasks as the source instance.

This method must be called before calling .done()

.getFactory()

  • returns a function.

Create's a function which returns a new copy of the source instance each time it's called.

This method must be called before calling .done()

.getStatus()

  • returns a string.

Possible Return Values:

  • "ready" .done() has not been called.
  • "running" .done() has been called, no tasks have been rejected, but not all tasks have been resolved either.
  • "closed" All tasks have been resolved or a task was rejected.

Class Task

The first argument passed to all taskCallback functions is an instance of this class.

.resolve(value)

  • value an optional value of any type.

Call this method to resolve the task. The value will be passed to any dependent tasks.

Calling this method more than once or after calling .reject(), has no effect.

.reject(err)

  • err an optional Error instance or string.

Call this method to reject the task. The err will be passed to all doneCallbacks as the first argument. If a string is given for err, a new Error instance will be constructed using the string as the error message.

Calling this method more than once or after calling .resolve() has no effect.

.isClosed()

  • returns a boolean.

Returns true if either .resolve() or .reject() have been called. Returns false otherwise.

.index

An integer value greater than or equal to zero.

If more than one task with the same name is added to job, this number indicates the order in which the currently running task was added.

.job

A Jobify instance.

This is the instance that the task was added to.

Install

npm i jobify

DownloadsWeekly Downloads

2

Version

1.0.0

License

MIT

Last publish

Collaborators

  • avatar