@orbit/core
Version:
Core library for Orbit - a flexible data access and synchronization layer.
108 lines (94 loc) • 2.47 kB
text/typescript
import { Task, Performer } from './task';
/**
* A `TaskProcessor` performs a `Task` by calling `perform()` on its target.
* This is triggered by calling `process()` on the processor.
*
* A processor maintains a promise that represents the eventual state (resolved
* or rejected) of the task. This promise is created upon construction, and
* will be returned by calling `settle()`.
*
* A task can be re-tried by first calling `reset()` on the processor. This
* will clear the processor's state and allow `process()` to be invoked again.
*/
export class TaskProcessor<
Type = string,
Data = unknown,
Options = unknown,
Result = unknown
> {
target: Performer<Type, Data, Options, Result>;
task: Task<Type, Data, Options>;
private _started!: boolean;
private _settled!: boolean;
private _settlement!: Promise<Result>;
private _success?: (resolution: Result) => void;
private _fail?: (e: Error) => void;
/**
* Creates an instance of TaskProcessor.
*/
constructor(
target: Performer<Type, Data, Options, Result>,
task: Task<Type, Data, Options>
) {
this.target = target;
this.task = task;
this.reset();
}
/**
* Clears the processor state, allowing for a fresh call to `process()`.
*/
reset(): void {
this._started = false;
this._settled = false;
this._settlement = new Promise((resolve, reject) => {
this._success = (r) => {
this._settled = true;
resolve(r);
};
this._fail = (e) => {
this._settled = true;
reject(e);
};
});
}
/**
* Has `process` been invoked?
*/
get started(): boolean {
return this._started;
}
/**
* Has promise settled, either via `process` or `reject`?
*/
get settled(): boolean {
return this._settled;
}
/**
* The eventual result of processing.
*/
settle(): Promise<Result> {
return this._settlement;
}
/**
* Invokes `perform` on the target.
*/
process(): Promise<Result> {
if (!this._started) {
this._started = true;
this.target.perform(this.task).then(this._success, this._fail);
}
return this.settle();
}
/**
* Reject the current promise with a specific error.
*/
reject(e: Error): void {
if (this._settled) {
throw new Error(
'TaskProcessor#reject can not be invoked when processing has already settled.'
);
} else if (this._fail) {
this._fail(e);
}
}
}