A controller for Lit that renders asynchronous tasks.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Core task execution and lifecycle management functionality for creating, running, and controlling asynchronous operations in Lit elements.
The main Task class that serves as a reactive controller for managing asynchronous operations.
/**
* A controller that performs an asynchronous task when its host element updates.
* Requests updates on the host element when the task starts and completes.
*/
class Task<T extends ReadonlyArray<unknown>, R> {
/** Controls automatic task execution */
autoRun: boolean | 'afterUpdate';
/** Result of the previous task run, if it resolved */
readonly value?: R;
/** Error from the previous task run, if it rejected */
readonly error?: unknown;
/** Current task status */
readonly status: TaskStatus;
/**
* Promise that resolves when the current task run is complete
* - If task is PENDING: Promise resolves when task completes
* - If task is COMPLETE: Promise resolves immediately with current value
* - If task is ERROR: Promise rejects immediately with current error
* - If task is INITIAL: Promise resolves immediately with undefined
*/
readonly taskComplete: Promise<R>;
}Two constructor overloads for creating Task instances.
/**
* Create a Task with a configuration object
* @param host - Lit element that owns this task
* @param config - Task configuration object
*/
constructor(host: ReactiveControllerHost, config: TaskConfig<T, R>);
/**
* Create a Task with individual parameters
* @param host - Lit element that owns this task
* @param task - The task function to execute
* @param args - Function that returns task arguments
*/
constructor(
host: ReactiveControllerHost,
task: TaskFunction<T, R>,
args?: ArgsFunction<T>
);Usage Examples:
import { LitElement } from "lit";
import { Task } from "@lit/task";
class MyElement extends LitElement {
// Using configuration object
task1 = new Task(this, {
task: async ([id]) => {
const response = await fetch(`/api/data/${id}`);
return response.json();
},
args: () => [this.dataId],
autoRun: true,
onComplete: (result) => console.log('Task completed:', result),
onError: (error) => console.error('Task failed:', error)
});
// Using individual parameters
task2 = new Task(
this,
async ([query]) => searchAPI(query),
() => [this.searchQuery]
);
}Configuration object for advanced task setup.
interface TaskConfig<T extends ReadonlyArray<unknown>, R> {
/** The task function to execute */
task: TaskFunction<T, R>;
/** Function that returns task arguments */
args?: ArgsFunction<T>;
/**
* Controls automatic task execution
* - true: Run during host update (default)
* - 'afterUpdate': Run after host update
* - false: Manual execution only
*/
autoRun?: boolean | 'afterUpdate';
/** Function to compare argument arrays for equality */
argsEqual?: (oldArgs: T, newArgs: T) => boolean;
/** Initial value to set task as completed */
initialValue?: R;
/** Callback when task completes successfully */
onComplete?: (value: R) => unknown;
/** Callback when task fails with error */
onError?: (error: unknown) => unknown;
}Methods for controlling task execution.
/**
* Manually run the task with optional custom arguments
* @param args - Optional arguments to use for this run
* @returns Promise that resolves when task completes
*/
async run(args?: T): Promise<void>;
/**
* Abort the currently pending task run
* @param reason - Optional reason for aborting
*/
abort(reason?: unknown): void;Methods that integrate with the host element's update cycle as part of the reactive controller pattern.
/**
* Called during host element update phase
* Triggers automatic task execution if autoRun is true
*/
hostUpdate(): void;
/**
* Called after host element update phase
* Triggers automatic task execution if autoRun is 'afterUpdate'
*/
hostUpdated(): void;Note: These methods are called automatically by Lit's reactive controller system. You typically don't need to call them manually.
Usage Examples:
// Manual task execution
await myTask.run();
// Run with custom arguments
await myTask.run(['custom', 'arguments']);
// Abort pending task
myTask.abort('User cancelled');
// Wait for task completion
try {
const result = await myTask.taskComplete;
console.log('Task result:', result);
} catch (error) {
console.error('Task failed:', error);
}
// Combining run and taskComplete
await myTask.run();
const result = await myTask.taskComplete;Function signatures for task implementation.
/**
* Function that performs the actual task work
* @param args - Arguments array from args function
* @param options - Task execution options including AbortSignal
* @returns Task result, Promise of result, or initialState symbol
*/
type TaskFunction<D extends ReadonlyArray<unknown>, R = unknown> = (
args: D,
options: TaskFunctionOptions
) => R | typeof initialState | Promise<R | typeof initialState>;
/**
* Function that returns arguments for task execution
* @returns Array of arguments to pass to task function
*/
type ArgsFunction<D extends ReadonlyArray<unknown>> = () => D;
/**
* Legacy alias for ArgsFunction (maintained for backward compatibility)
*/
type DepsFunction<D extends ReadonlyArray<unknown>> = ArgsFunction<D>;
/**
* Options passed to task functions
*/
interface TaskFunctionOptions {
/** AbortSignal for cancelling the task */
signal: AbortSignal;
}Special symbol for resetting task state.
/**
* Special value that can be returned from task functions to reset the task
* status to INITIAL state
*/
const initialState: unique symbol;Usage Example:
const conditionalTask = new Task(this, {
task: async ([shouldRun]) => {
if (!shouldRun) {
return initialState; // Reset to INITIAL state
}
return await performWork();
},
args: () => [this.shouldRunTask]
});