Created
July 27, 2017 13:17
-
-
Save timhall/c3011828c76deb2fafd9e1e5e4836453 to your computer and use it in GitHub Desktop.
task.run, unified approach
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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