Running Tasks
APIExecuting tasks and handling cancellation
Overview
Tasks are lazy - they don't execute until explicitly run. This section covers how to execute tasks and handle cancellation.
Task.run
The primary way to execute a task:
import { Task } from '@w5s/task';
import { Result } from '@w5s/core';
const myTask = Task.resolve(42);
// Run and get the result
const result = await Task.run(myTask);
if (Result.isOk(result)) {
console.log('Success:', result.value);
} else {
console.error('Error:', result.error);
}
Cancellation
Tasks can be cancelled by passing a canceler reference to Task.run:
import { Task } from '@w5s/task';
import { Ref } from '@w5s/core';
// Create a canceler reference
const controller = new AbortController();
// Run with canceler
const resultPromise = Task.run(myTask, { signal: controller.signal });
// Cancel the task
controller.abort();
For detailed information on making tasks cancellable and advanced patterns, see Cancelling tasks.
Using task.run() Method
Tasks also have a run method for convenience:
import { Task } from '@w5s/task';
const myTask = Task.create(() => Task.ok(42));
// Direct method call
const result = await myTask.run();
Best Practices
Keep Task.run at the Edge
Place Task.run calls at the edges of your application (entry points, event handlers, etc.) to maintain the benefits of lazy evaluation:
// ✓ Good: Run at the application entry point
async function main() {
const program = buildProgram();
const result = await Task.run(program);
handleResult(result);
}
// ⤫ Bad: Running tasks inside business logic
function processData(data: Data) {
const task = transform(data);
return Task.run(task); // Loses composability
}
Handle Both Result Cases
Always handle both success and error cases:
import { Task } from '@w5s/task';
import { Result } from '@w5s/core';
const result = await Task.run(myTask);
// ✓ Good: Explicit handling
if (Result.isOk(result)) {
processValue(result.value);
} else {
handleError(result.error);
}
// ⤫ Bad: Ignoring potential errors
const value = (await Task.run(myTask)).value; // Might be undefined!
FAQ
When should I use Task vs Promise?
Use Task when:
- You need lazy evaluation
- You need cancellation
- You want explicit error handling with
Result - You're building composable async workflows
Use Promise when:
- You need immediate execution
- Inter-operating with APIs that expect Promises
- Simple one-off async operations
Can I convert between Task and Promise?
Yes! Task.run returns a Promise, and you can wrap Promises in Tasks:
// Promise to Task
const fromPromise = Task.create(async () => {
const value = await somePromise;
return Task.ok(value);
});
// Task to Promise
const toPromise = Task.run(someTask);