functype 0.8.83 → 0.8.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Either-CncND8cm.d.ts → Either-BlY4VB1r.d.ts} +3 -3
- package/dist/{chunk-JMCOLAJY.mjs → chunk-JAPOUVPL.mjs} +2 -2
- package/dist/chunk-JAPOUVPL.mjs.map +1 -0
- package/dist/either/index.d.ts +1 -1
- package/dist/either/index.mjs +1 -1
- package/dist/fpromise/index.d.ts +1 -1
- package/dist/fpromise/index.mjs +1 -1
- package/dist/index.d.ts +3 -28
- package/dist/index.mjs +1 -1
- package/dist/list/index.d.ts +1 -1
- package/dist/list/index.mjs +1 -1
- package/dist/map/index.d.ts +1 -1
- package/dist/map/index.mjs +1 -1
- package/dist/option/index.d.ts +1 -1
- package/dist/option/index.mjs +1 -1
- package/dist/set/index.d.ts +1 -1
- package/dist/set/index.mjs +1 -1
- package/dist/try/index.d.ts +1 -1
- package/dist/try/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-JMCOLAJY.mjs.map +0 -1
- package/readme/BUNDLE_OPTIMIZATION.md +0 -74
- package/readme/FPromise-Assessment.md +0 -43
- package/readme/HKT.md +0 -110
- package/readme/ROADMAP.md +0 -113
- package/readme/TASK-IMPLEMENTATION.md +0 -290
- package/readme/TASK-TODO.md +0 -40
- package/readme/TASK-UPDATES.md +0 -64
- package/readme/TUPLE-EXAMPLES.md +0 -76
- package/readme/TaskMigration.md +0 -129
- package/readme/ai-guide.md +0 -406
- package/readme/examples.md +0 -2093
- package/readme/quick-reference.md +0 -514
- package/readme/task-cancellation-progress.md +0 -258
- package/readme/task-error-handling.md +0 -127
- package/readme/task-quick-reference.md +0 -157
- package/readme/tasks.md +0 -205
- package/readme/type-index.md +0 -238
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
# Task Cancellation and Progress Tracking
|
|
2
|
-
|
|
3
|
-
The Task module in functype now provides robust support for cancellation and progress tracking of asynchronous operations. This guide explains how to use these advanced features.
|
|
4
|
-
|
|
5
|
-
## Cancellation
|
|
6
|
-
|
|
7
|
-
Task cancellation allows you to safely stop long-running operations that are no longer needed, improving resource usage and user experience.
|
|
8
|
-
|
|
9
|
-
### Creating Cancellable Tasks
|
|
10
|
-
|
|
11
|
-
```typescript
|
|
12
|
-
import { Task } from "@/core"
|
|
13
|
-
|
|
14
|
-
// Create a cancellable task
|
|
15
|
-
const { task, cancel } = Task.cancellable(async (token) => {
|
|
16
|
-
// The token is passed to your task function
|
|
17
|
-
|
|
18
|
-
// Use token.isCancelled to check cancellation status
|
|
19
|
-
if (token.isCancelled) {
|
|
20
|
-
return "Cancelled before starting work"
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
// Perform your long-running operation, checking cancellation periodically
|
|
24
|
-
for (const item of largeDataset) {
|
|
25
|
-
if (token.isCancelled) {
|
|
26
|
-
return "Cancelled during processing"
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
await processItem(item)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return "Completed successfully"
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
// Execute task
|
|
36
|
-
task.then((result) => console.log(result)).catch((error) => console.error(error))
|
|
37
|
-
|
|
38
|
-
// Later, if needed, cancel the operation
|
|
39
|
-
cancel()
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Cancellation Token Features
|
|
43
|
-
|
|
44
|
-
The `CancellationToken` provides three key properties:
|
|
45
|
-
|
|
46
|
-
1. **isCancelled**: Boolean flag indicating cancellation status
|
|
47
|
-
2. **signal**: An `AbortSignal` compatible with fetch and other DOM APIs
|
|
48
|
-
3. **onCancel**: Method to register callbacks that execute on cancellation
|
|
49
|
-
|
|
50
|
-
### Integration with Web APIs
|
|
51
|
-
|
|
52
|
-
The cancellation token's `signal` property works with any API that accepts AbortSignal:
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
const { task, cancel } = Task.cancellable(async (token) => {
|
|
56
|
-
// Pass the signal to fetch
|
|
57
|
-
const response = await fetch("https://api.example.com/data", {
|
|
58
|
-
signal: token.signal,
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
// Process response...
|
|
62
|
-
return await response.json()
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
// Cancel after 5 seconds if still running
|
|
66
|
-
setTimeout(cancel, 5000)
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### Custom Cancellation Handlers
|
|
70
|
-
|
|
71
|
-
Register cleanup code that runs when cancellation occurs:
|
|
72
|
-
|
|
73
|
-
```typescript
|
|
74
|
-
const { task, cancel } = Task.cancellable(async (token) => {
|
|
75
|
-
// Setup resources
|
|
76
|
-
const resources = await allocateExpensiveResources()
|
|
77
|
-
|
|
78
|
-
// Register cleanup on cancellation
|
|
79
|
-
token.onCancel(() => {
|
|
80
|
-
resources.dispose()
|
|
81
|
-
console.log("Resources cleaned up")
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
try {
|
|
85
|
-
// Do work with resources...
|
|
86
|
-
return result
|
|
87
|
-
} finally {
|
|
88
|
-
// This still runs even with cancellation
|
|
89
|
-
resources.dispose()
|
|
90
|
-
}
|
|
91
|
-
})
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Progress Tracking
|
|
95
|
-
|
|
96
|
-
For long-running operations, reporting progress provides better feedback to users.
|
|
97
|
-
|
|
98
|
-
### Basic Progress Tracking
|
|
99
|
-
|
|
100
|
-
```typescript
|
|
101
|
-
// Create a task with progress tracking
|
|
102
|
-
const { task, currentProgress } = Task.withProgress(
|
|
103
|
-
async (updateProgress) => {
|
|
104
|
-
// Start at 0%
|
|
105
|
-
updateProgress(0)
|
|
106
|
-
|
|
107
|
-
// Process in chunks
|
|
108
|
-
for (let i = 0; i < 10; i++) {
|
|
109
|
-
// Do some work...
|
|
110
|
-
await processChunk(i)
|
|
111
|
-
|
|
112
|
-
// Update progress (0-100)
|
|
113
|
-
updateProgress((i + 1) * 10)
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return "Completed successfully"
|
|
117
|
-
},
|
|
118
|
-
// Optional callback receives progress updates
|
|
119
|
-
(percent) => {
|
|
120
|
-
console.log(`Progress: ${percent}%`)
|
|
121
|
-
updateProgressBar(percent)
|
|
122
|
-
},
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
// Execute the task
|
|
126
|
-
const result = await task
|
|
127
|
-
|
|
128
|
-
// Get current progress anytime
|
|
129
|
-
console.log(`Current progress: ${currentProgress()}%`)
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
### Combining Progress with Cancellation
|
|
133
|
-
|
|
134
|
-
Both features can be used together for maximum control:
|
|
135
|
-
|
|
136
|
-
```typescript
|
|
137
|
-
const { task, cancel, currentProgress } = Task.withProgress(async (updateProgress, token) => {
|
|
138
|
-
updateProgress(0)
|
|
139
|
-
|
|
140
|
-
for (let i = 0; i < 100; i++) {
|
|
141
|
-
// Check cancellation
|
|
142
|
-
if (token.isCancelled) {
|
|
143
|
-
return "Operation cancelled"
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
await processItem(i)
|
|
147
|
-
updateProgress(i + 1)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return "All items processed"
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
// Show progress in UI
|
|
154
|
-
const interval = setInterval(() => {
|
|
155
|
-
updateUI(`Progress: ${currentProgress()}%`)
|
|
156
|
-
|
|
157
|
-
// Once complete, clear the interval
|
|
158
|
-
if (currentProgress() === 100) {
|
|
159
|
-
clearInterval(interval)
|
|
160
|
-
}
|
|
161
|
-
}, 100)
|
|
162
|
-
|
|
163
|
-
// Allow cancellation from UI
|
|
164
|
-
cancelButton.addEventListener("click", () => {
|
|
165
|
-
cancel()
|
|
166
|
-
})
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
### AsyncWithProgress Method
|
|
170
|
-
|
|
171
|
-
For direct method usage without the object destructuring pattern:
|
|
172
|
-
|
|
173
|
-
```typescript
|
|
174
|
-
const task = Task().AsyncWithProgress(
|
|
175
|
-
(updateProgress) => {
|
|
176
|
-
// Update progress as needed
|
|
177
|
-
updateProgress(25)
|
|
178
|
-
|
|
179
|
-
// Return result
|
|
180
|
-
return "done"
|
|
181
|
-
},
|
|
182
|
-
(percent) => console.log(`Progress: ${percent}%`),
|
|
183
|
-
(error) => error, // Optional error handler
|
|
184
|
-
() => {}, // Optional finally function
|
|
185
|
-
token, // Optional cancellation token
|
|
186
|
-
)
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
## Racing Tasks
|
|
190
|
-
|
|
191
|
-
When multiple asynchronous operations are running in parallel, you might want to take the first to complete:
|
|
192
|
-
|
|
193
|
-
```typescript
|
|
194
|
-
// Create multiple tasks
|
|
195
|
-
const task1 = Task().Async(async () => /* slow operation */)
|
|
196
|
-
const task2 = Task().Async(async () => /* medium operation */)
|
|
197
|
-
const task3 = Task().Async(async () => /* fast operation */)
|
|
198
|
-
|
|
199
|
-
// Race the tasks with a 5 second timeout
|
|
200
|
-
const result = await Task.race(
|
|
201
|
-
[task1, task2, task3],
|
|
202
|
-
5000, // Optional timeout in ms
|
|
203
|
-
{ name: "DataRace" } // Optional task params
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
// Result will be from the first task to complete
|
|
207
|
-
// Or will throw an error if all tasks fail or the timeout is reached
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
## Node.js Callback Integration
|
|
211
|
-
|
|
212
|
-
Convert traditional Node.js callback functions to Task:
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
import { readFile } from "fs"
|
|
216
|
-
import { Task } from "@/core"
|
|
217
|
-
|
|
218
|
-
// Convert Node.js callback function to Task
|
|
219
|
-
const readFileTask = Task.fromNodeCallback<string, [string, string]>(readFile)
|
|
220
|
-
|
|
221
|
-
// Use the task
|
|
222
|
-
try {
|
|
223
|
-
const content = await readFileTask("config.json", "utf8")
|
|
224
|
-
console.log(content)
|
|
225
|
-
} catch (error) {
|
|
226
|
-
console.error("Error reading file:", error)
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
## Best Practices
|
|
231
|
-
|
|
232
|
-
1. **Check Cancellation Regularly**: Check the token status at appropriate intervals in long-running tasks
|
|
233
|
-
2. **Clean Up Resources**: Use `onCancel` or `finally` blocks to ensure resources are released
|
|
234
|
-
3. **Progress Granularity**: Don't update progress too frequently to avoid performance overhead
|
|
235
|
-
4. **Timeout Handling**: Use timeouts with `Task.race` to prevent indefinitely waiting for operations
|
|
236
|
-
5. **Error Propagation**: Remember that cancellation generates error objects with task context
|
|
237
|
-
|
|
238
|
-
## Cancellation vs. Errors
|
|
239
|
-
|
|
240
|
-
A cancelled task will reject with a cancellation error. If you need to distinguish between regular errors and cancellation:
|
|
241
|
-
|
|
242
|
-
```typescript
|
|
243
|
-
try {
|
|
244
|
-
await task
|
|
245
|
-
} catch (error) {
|
|
246
|
-
if (error.message.includes("cancelled")) {
|
|
247
|
-
// Handle cancellation
|
|
248
|
-
} else {
|
|
249
|
-
// Handle regular error
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
```
|
|
253
|
-
|
|
254
|
-
## See Also
|
|
255
|
-
|
|
256
|
-
- [Task Error Handling](./task-error-handling.md)
|
|
257
|
-
- [Task Implementation Details](./TASK-IMPLEMENTATION.md)
|
|
258
|
-
- [Task Migration Guide](./TaskMigration.md)
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
# Task Error Handling
|
|
2
|
-
|
|
3
|
-
The `Task` module in Functype provides robust error handling capabilities, including the ability to include task identifiers in error objects. This guide explains how to take advantage of these features.
|
|
4
|
-
|
|
5
|
-
## Named Task Errors
|
|
6
|
-
|
|
7
|
-
When creating a `Task`, you can provide an optional name and description:
|
|
8
|
-
|
|
9
|
-
```typescript
|
|
10
|
-
const namedTask = Task({
|
|
11
|
-
name: "UserRegistration",
|
|
12
|
-
description: "Handles user registration process",
|
|
13
|
-
})
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
When an error occurs within this task, the task name will be referenced in the error:
|
|
17
|
-
|
|
18
|
-
1. The `Throwable` object created from the error will include:
|
|
19
|
-
- The task name as the error's `name` property
|
|
20
|
-
- A `taskInfo` property containing both the name and description
|
|
21
|
-
|
|
22
|
-
2. The `TaskException` object will include:
|
|
23
|
-
- The `_task` property with the name and description
|
|
24
|
-
- The original error wrapped with the task name and info
|
|
25
|
-
|
|
26
|
-
## Examples
|
|
27
|
-
|
|
28
|
-
### Sync Task Error
|
|
29
|
-
|
|
30
|
-
```typescript
|
|
31
|
-
const namedTask = Task({ name: "UserRegistration" })
|
|
32
|
-
|
|
33
|
-
const result = namedTask.Sync(() => {
|
|
34
|
-
throw new Error("Invalid user data")
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
// The error (within the Left) will have:
|
|
38
|
-
// - name: "UserRegistration"
|
|
39
|
-
// - message: "Invalid user data"
|
|
40
|
-
// - taskInfo: { name: "UserRegistration", description: "..." }
|
|
41
|
-
|
|
42
|
-
console.log(result.value.name) // "UserRegistration"
|
|
43
|
-
console.log(result._task.name) // "UserRegistration"
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
### Async Task Error
|
|
47
|
-
|
|
48
|
-
```typescript
|
|
49
|
-
try {
|
|
50
|
-
await Task({ name: "DataProcessing" }).Async(async () => {
|
|
51
|
-
throw new Error("Processing failed")
|
|
52
|
-
})
|
|
53
|
-
} catch (error) {
|
|
54
|
-
// The error will have:
|
|
55
|
-
// - name: "DataProcessing"
|
|
56
|
-
// - message: "Processing failed"
|
|
57
|
-
// - taskInfo: { name: "DataProcessing", description: "..." }
|
|
58
|
-
|
|
59
|
-
console.log(error.name) // "DataProcessing"
|
|
60
|
-
console.log(error.taskInfo) // { name: "DataProcessing", description: "..." }
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Using Task.fail Companion Function
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
const error = new Error("Authentication failed")
|
|
68
|
-
const result = Task.fail(error, { userId: 123 }, { name: "AuthService" })
|
|
69
|
-
|
|
70
|
-
// The TaskException contains:
|
|
71
|
-
console.log(result.value.name) // "AuthService"
|
|
72
|
-
console.log(result.value.message) // "Authentication failed"
|
|
73
|
-
console.log(result.value.data) // { userId: 123 }
|
|
74
|
-
console.log(result.value.taskInfo) // { name: "AuthService", description: "..." }
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
## Benefits
|
|
78
|
-
|
|
79
|
-
Including task names in errors provides several advantages:
|
|
80
|
-
|
|
81
|
-
1. **Better Error Identification**: Easily identify which task produced an error
|
|
82
|
-
2. **Improved Debugging**: Quickly locate the source of exceptions
|
|
83
|
-
3. **Enhanced Logging**: Structured error information for logs and monitoring
|
|
84
|
-
4. **Error Context**: Maintain context about what operation was being performed
|
|
85
|
-
5. **Consistent Error Format**: All errors follow the same structure
|
|
86
|
-
|
|
87
|
-
## Error Propagation
|
|
88
|
-
|
|
89
|
-
Task names and information propagate through the error handling chain:
|
|
90
|
-
|
|
91
|
-
```typescript
|
|
92
|
-
const result = Task({ name: "UserService" }).Sync(
|
|
93
|
-
() => {
|
|
94
|
-
throw new Error("User not found")
|
|
95
|
-
},
|
|
96
|
-
(error) => `Could not process request: ${error.message}`,
|
|
97
|
-
)
|
|
98
|
-
|
|
99
|
-
// The resulting error maintains the task name even through the error handler
|
|
100
|
-
console.log(result.value.name) // "UserService"
|
|
101
|
-
console.log(result.value.message) // "Could not process request: User not found"
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## With finally Blocks
|
|
105
|
-
|
|
106
|
-
Task names are preserved even when errors occur in finally blocks:
|
|
107
|
-
|
|
108
|
-
```typescript
|
|
109
|
-
try {
|
|
110
|
-
await Task({ name: "CleanupTask" }).Async(
|
|
111
|
-
async () => "success",
|
|
112
|
-
async (error) => error,
|
|
113
|
-
() => {
|
|
114
|
-
throw new Error("Cleanup failed")
|
|
115
|
-
},
|
|
116
|
-
)
|
|
117
|
-
} catch (error) {
|
|
118
|
-
// The error from the finally block still includes the task name
|
|
119
|
-
console.log(error.name) // "CleanupTask"
|
|
120
|
-
console.log(error.message) // "Cleanup failed"
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
## See Also
|
|
125
|
-
|
|
126
|
-
- [Task Module Examples](./examples/task-named-errors.ts)
|
|
127
|
-
- [Task API Documentation](./quick-reference.md#task)
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
# Task Quick Reference
|
|
2
|
-
|
|
3
|
-
## Basic Usage
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
import { Task } from "@/core"
|
|
7
|
-
|
|
8
|
-
// Synchronous task with explicit error handling
|
|
9
|
-
const syncResult = Task().Sync(
|
|
10
|
-
() => "success", // Main operation
|
|
11
|
-
(error) => error, // Error handler (optional)
|
|
12
|
-
() => {}, // Finally (optional)
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
// syncResult is Either<Throwable, string>
|
|
16
|
-
if (syncResult.isRight()) {
|
|
17
|
-
console.log("Success:", syncResult.value) // "success"
|
|
18
|
-
} else {
|
|
19
|
-
console.log("Error:", syncResult.value) // Throwable
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Asynchronous task (Promise-based)
|
|
23
|
-
const asyncResult = await Task().Async(
|
|
24
|
-
async () => "async success", // Main operation (async)
|
|
25
|
-
async (error) => error, // Error handler (optional, async)
|
|
26
|
-
async () => {}, // Finally (optional, async)
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
// asyncResult is the unwrapped value: "async success"
|
|
30
|
-
// If error occurs, the promise rejects with Throwable
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Task Naming and Error Context
|
|
34
|
-
|
|
35
|
-
```typescript
|
|
36
|
-
// Named task provides context for errors
|
|
37
|
-
const userTask = Task({
|
|
38
|
-
name: "UserService",
|
|
39
|
-
description: "Handles user operations",
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
// Error will include task name and description
|
|
43
|
-
try {
|
|
44
|
-
await userTask.Async(async () => {
|
|
45
|
-
throw new Error("Not found")
|
|
46
|
-
})
|
|
47
|
-
} catch (error) {
|
|
48
|
-
console.log(error.name) // "UserService"
|
|
49
|
-
console.log(error.message) // "Not found"
|
|
50
|
-
console.log(error.taskInfo) // { name: "UserService", description: "..." }
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Companion Functions
|
|
55
|
-
|
|
56
|
-
```typescript
|
|
57
|
-
// Create success/failure results
|
|
58
|
-
const success = Task.success("data", { name: "SuccessTask" })
|
|
59
|
-
const failure = Task.fail(new Error("Failed"), { context: true }, { name: "FailTask" })
|
|
60
|
-
|
|
61
|
-
// Convert promise function to task
|
|
62
|
-
const fetchTask = Task.fromPromise(fetch, { name: "FetchTask" })
|
|
63
|
-
const response = await fetchTask("https://api.example.com/data")
|
|
64
|
-
|
|
65
|
-
// Convert task result to promise
|
|
66
|
-
const promise = Task.toPromise(success) // Promise<string>
|
|
67
|
-
|
|
68
|
-
// Convert Node.js callback to task
|
|
69
|
-
const readFileTask = Task.fromNodeCallback(fs.readFile)
|
|
70
|
-
const content = await readFileTask("config.json", "utf8")
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
## Cancellation
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
// Create cancellable task
|
|
77
|
-
const { task, cancel } = Task.cancellable(async (token) => {
|
|
78
|
-
// Check cancellation
|
|
79
|
-
if (token.isCancelled) return "Already cancelled"
|
|
80
|
-
|
|
81
|
-
// Use with fetch
|
|
82
|
-
const response = await fetch(url, { signal: token.signal })
|
|
83
|
-
|
|
84
|
-
// Register cleanup on cancellation
|
|
85
|
-
token.onCancel(() => {
|
|
86
|
-
console.log("Task cancelled")
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
return await response.json()
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
// Later: cancel the task
|
|
93
|
-
cancel()
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Progress Tracking
|
|
97
|
-
|
|
98
|
-
```typescript
|
|
99
|
-
// Create task with progress updates
|
|
100
|
-
const { task, currentProgress, cancel } = Task.withProgress(
|
|
101
|
-
async (updateProgress, token) => {
|
|
102
|
-
updateProgress(0) // Initial progress
|
|
103
|
-
|
|
104
|
-
// Do work in chunks
|
|
105
|
-
for (let i = 0; i < 10; i++) {
|
|
106
|
-
if (token.isCancelled) break
|
|
107
|
-
await processChunk(i)
|
|
108
|
-
updateProgress((i + 1) * 10) // Update progress (0-100)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return "Complete"
|
|
112
|
-
},
|
|
113
|
-
(percent) => {
|
|
114
|
-
console.log(`Progress: ${percent}%`)
|
|
115
|
-
},
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
// Get current progress anytime
|
|
119
|
-
console.log(`Status: ${currentProgress()}%`)
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## Task Racing
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
// Race multiple tasks
|
|
126
|
-
const result = await Task.race(
|
|
127
|
-
[task1, task2, task3], // Array of tasks to race
|
|
128
|
-
5000, // Optional timeout in milliseconds
|
|
129
|
-
{ name: "RaceTask" }, // Optional task params
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
// Result is from the first task to complete
|
|
133
|
-
// Throws if all tasks fail or timeout is reached
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
## Task Composition
|
|
137
|
-
|
|
138
|
-
```typescript
|
|
139
|
-
// Sequential composition
|
|
140
|
-
const result = await Task().Async(async () => {
|
|
141
|
-
const first = await Task().Async(async () => "first")
|
|
142
|
-
const second = await Task().Async(async () => first + " second")
|
|
143
|
-
return second // "first second"
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
// Error handling composition
|
|
147
|
-
try {
|
|
148
|
-
await Task({ name: "Outer" }).Async(async () => {
|
|
149
|
-
await Task({ name: "Inner" }).Async(async () => {
|
|
150
|
-
throw new Error("Inner error")
|
|
151
|
-
})
|
|
152
|
-
})
|
|
153
|
-
} catch (error) {
|
|
154
|
-
// Error message is from inner task: "Inner error"
|
|
155
|
-
// But task context is from outer task: { name: "Outer" }
|
|
156
|
-
}
|
|
157
|
-
```
|