Skip to content

Commit

Permalink
Task add onComplete and onError (#3287)
Browse files Browse the repository at this point in the history
  • Loading branch information
e111077 committed Sep 29, 2022
1 parent 7a9fc0f commit 02b0b7b
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/lazy-moons-train.md
@@ -0,0 +1,5 @@
---
'@lit-labs/task': minor
---

Adds onComplete and onError callbacks
16 changes: 16 additions & 0 deletions packages/labs/task/src/task.ts
Expand Up @@ -44,6 +44,8 @@ export interface TaskConfig<T extends ReadonlyArray<unknown>, R> {
task: TaskFunction<T, R>;
args?: ArgsFunction<T>;
autoRun?: boolean;
onComplete?: (value: R) => unknown;
onError?: (error: unknown) => unknown;
}

// TODO(sorvell): Some issues:
Expand Down Expand Up @@ -109,6 +111,8 @@ export class Task<
private _host: ReactiveControllerHost;
private _value?: R;
private _error?: unknown;
private _onComplete?: (result: R) => unknown;
private _onError?: (error: unknown) => unknown;
status: TaskStatus = TaskStatus.INITIAL;

/**
Expand Down Expand Up @@ -144,6 +148,8 @@ export class Task<
typeof task === 'object' ? task : ({task, args} as TaskConfig<T, R>);
this._task = taskConfig.task;
this._getArgs = taskConfig.args;
this._onComplete = taskConfig.onComplete;
this._onError = taskConfig.onError;
if (taskConfig.autoRun !== undefined) {
this.autoRun = taskConfig.autoRun;
}
Expand Down Expand Up @@ -211,9 +217,19 @@ export class Task<
this.status = TaskStatus.INITIAL;
} else {
if (error === undefined) {
try {
this._onComplete?.(result as R);
} catch {
// Ignore user errors from onComplete.
}
this.status = TaskStatus.COMPLETE;
this._resolveTaskComplete(result as R);
} else {
try {
this._onError?.(error);
} catch {
// Ignore user errors from onError.
}
this.status = TaskStatus.ERROR;
this._rejectTaskComplete(error);
}
Expand Down
76 changes: 73 additions & 3 deletions packages/labs/task/src/test/task_test.ts
Expand Up @@ -27,7 +27,7 @@ suite('Task', () => {
b: string;
c?: string;
resolveTask: () => void;
rejectTask: () => void;
rejectTask: (error?: string) => void;
taskValue?: string;
renderedStatus?: string;
}
Expand All @@ -46,7 +46,7 @@ suite('Task', () => {
c?: string;

resolveTask!: () => void;
rejectTask!: () => void;
rejectTask!: (error?: string) => void;

taskValue?: string;
renderedStatus?: string;
Expand All @@ -56,7 +56,7 @@ suite('Task', () => {
const taskConfig = {
task: (...args: unknown[]) =>
new Promise((resolve, reject) => {
this.rejectTask = () => reject(`error`);
this.rejectTask = (error = 'error') => reject(error);
this.resolveTask = () => resolve(args.join(','));
}),
};
Expand Down Expand Up @@ -458,4 +458,74 @@ suite('Task', () => {
);
};
});

test('onComplete callback is called', async () => {
let numOnCompleteInvocations = 0;
let lastOnCompleteResult: string | undefined = undefined;
const el = getTestElement({
args: () => [el.a, el.b],
onComplete: (result) => {
numOnCompleteInvocations++;
lastOnCompleteResult = result;
},
});
await renderElement(el);
assert.equal(el.task.status, TaskStatus.PENDING);
assert.equal(numOnCompleteInvocations, 0);
assert.equal(lastOnCompleteResult, undefined);
el.resolveTask();
await tasksUpdateComplete();
assert.equal(el.task.status, TaskStatus.COMPLETE);
assert.equal(numOnCompleteInvocations, 1);
assert.equal(lastOnCompleteResult, 'a,b');

numOnCompleteInvocations = 0;

// Called after every task completion.
el.a = 'a1';
await tasksUpdateComplete();
assert.equal(el.task.status, TaskStatus.PENDING);
assert.equal(numOnCompleteInvocations, 0);
assert.equal(lastOnCompleteResult, 'a,b');
el.resolveTask();
await tasksUpdateComplete();
assert.equal(el.task.status, TaskStatus.COMPLETE);
assert.equal(numOnCompleteInvocations, 1);
assert.equal(lastOnCompleteResult, 'a1,b');
});

test('onError callback is called', async () => {
let numOnErrorInvocations = 0;
let lastOnErrorResult: string | undefined = undefined;
const el = getTestElement({
args: () => [el.a, el.b],
onError: (error) => {
numOnErrorInvocations++;
lastOnErrorResult = error as string;
},
});
await renderElement(el);
assert.equal(el.task.status, TaskStatus.PENDING);
assert.equal(numOnErrorInvocations, 0);
assert.equal(lastOnErrorResult, undefined);
el.rejectTask('error');
await tasksUpdateComplete();
assert.equal(el.task.status, TaskStatus.ERROR);
assert.equal(numOnErrorInvocations, 1);
assert.equal(lastOnErrorResult, 'error');

numOnErrorInvocations = 0;

// Called after every task error.
el.a = 'a1';
await tasksUpdateComplete();
assert.equal(el.task.status, TaskStatus.PENDING);
assert.equal(numOnErrorInvocations, 0);
assert.equal(lastOnErrorResult, 'error');
el.rejectTask('error2');
await tasksUpdateComplete();
assert.equal(el.task.status, TaskStatus.ERROR);
assert.equal(numOnErrorInvocations, 1);
assert.equal(lastOnErrorResult, 'error2');
});
});

0 comments on commit 02b0b7b

Please sign in to comment.