Skip to content

Instantly share code, notes, and snippets.

@timhall
Created July 27, 2017 13:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timhall/c3011828c76deb2fafd9e1e5e4836453 to your computer and use it in GitHub Desktop.
Save timhall/c3011828c76deb2fafd9e1e5e4836453 to your computer and use it in GitHub Desktop.
task.run, unified approach
const co = require('bluebird').coroutine;
let taskId = 0;
class Task {
constructor(values = {}) {
const { id = `task${taskId++}`, files = [], globs = [], value } = values;
this.id = id;
this.files = files;
this.globs = globs;
this.value = value;
this.result = Promise.resolve(this.state);
this._index = 0;
}
get _() { return { files: this.files, globs: this.globs }; }
get state() { return { id: this.id, files: this.files, globs: this.globs, value: this.value }; }
run(fn, ...options) {
const id = `${this.id}_${fn.name}${this._index++}`;
// To avoid race issues with promise chain:
// - `next` task/promise that is returned
// - `context` task/promise that is passed to chain
const next = new Task({ id });
const context = new Task({ id: `${id}c` });
next.result = this.result.then(async () => {
context.files = this.files.slice();
context.globs = this.globs.slice();
context.value = this.value;
let result = await co(fn)(context, ...options);
// When returning original context, explicitly override
// (strange transient behavior can result otherwise)
if (result && result.id === context.id) {
result = context;
}
if (result && result.files && result.globs) {
next.files = result.files;
next.globs = result.globs;
next.value = undefined;
} else {
next.files = context.files;
next.globs = context.globs;
next.value = result;
}
return next.state;
});
return next;
}
then(f, r) { return this.result.then(f, r); }
catch(r) { return this.result.catch(r); }
static get [Symbol.species || '@@species']() { return Promise; }
}
const plugins = {
// ...
};
for (let key in plugins) {
Task.prototype[key] = function(...options) {
return this.run(plugins[key], ...options);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment