Created
August 13, 2020 18:00
-
-
Save Gozala/2a2a1f6d7ee78de6d28ccd85518732ea to your computer and use it in GitHub Desktop.
This file contains 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
/** | |
* @template T, X, A | |
* @typedef {import('./protocol').Process<T, X, A>} Process | |
*/ | |
/** | |
* @template X, T | |
* @typedef {import('./protocol').Task<X, T>} Task | |
*/ | |
/** | |
* @template T | |
* @implements {AsyncIterable<T>} | |
*/ | |
class Effect { | |
/** | |
* @template T - Message produced by performing a task. | |
* @template X - An error that task could produce. | |
* @template A - Result on succesful task completion. | |
* @param {Task<X, A>} task | |
* @param {(value:A) => T} succeed | |
* @param {(error:X) => T} fail | |
* @returns {Effect<T>} | |
*/ | |
static perform (task, succeed, fail) { | |
return new Perfrom(task, succeed, fail) | |
} | |
/** | |
* @template T - Message produced by performing a task. | |
* @template M - Messaeg produced by the task. | |
* @template X - An error that task could produce. | |
* @template R - Result on succesful task completion. | |
* @param {() => Process<M, X, R>} task | |
* @param {(message:M) => T} send | |
* @param {(value:R) => T} succeed | |
* @param {(error:X) => T} fail | |
* @returns {Effect<T>} | |
*/ | |
static spawn (task, send, succeed, fail) { | |
return new Spawn(task, send, succeed, fail) | |
} | |
/** | |
* @returns {AsyncIterator<T>} | |
*/ | |
async * [Symbol.asyncIterator] () { | |
} | |
} | |
/** | |
* @template T, X, R | |
* @extends {Effect<T>} | |
*/ | |
class Perfrom extends Effect { | |
/** | |
* @param {Task<X, R>} task | |
* @param {(value:R) => T} succeed | |
* @param {(error:X) => T} fail | |
*/ | |
constructor (task, succeed, fail) { | |
super() | |
this.task = task | |
this.succeed = succeed | |
this.fail = fail | |
} | |
async * [Symbol.asyncIterator] () { | |
try { | |
const value = await this.task() | |
yield this.succeed(value) | |
} catch (error) { | |
yield this.fail(error) | |
} | |
} | |
} | |
/** | |
* @template T, M, X, R | |
* @extends {Effect<T>} | |
*/ | |
class Spawn extends Effect { | |
/** | |
* @param {() => Process<M, X, R>} task | |
* @param {(message:M) => T} send | |
* @param {(value:R) => T} succeed | |
* @param {(error:X) => T} fail | |
*/ | |
constructor (task, send, succeed, fail) { | |
super() | |
this.task = task | |
this.send = send | |
this.succeed = succeed | |
this.fail = fail | |
} | |
async * [Symbol.asyncIterator] () { | |
try { | |
const process = this.task() | |
while (true) { | |
const next = await process.next() | |
if (next.done) { | |
yield this.succeed(next.value) | |
break | |
} else { | |
yield this.send(next.value) | |
} | |
} | |
} catch (error) { | |
yield this.fail(error) | |
} | |
} | |
} |
This file contains 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
export interface Future<X, T> extends Promise<T> { | |
then(succeed: (value: T) => any, fail: (error: X) => any): any | |
} | |
export interface Process<M, X, T> extends AsyncGenerator<M, T, never> { | |
next(...args: []): Future<X, IteratorResult<M, T>> | |
} | |
export type Task<X, A> = () => Future<X, A> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment