0
# Task System
1
2
Asynchronous task scheduling and management system that categorizes async work into microtasks, macrotasks, and event tasks.
3
4
## Capabilities
5
6
### Base Task Interface
7
8
Core task interface that represents all asynchronous work in zones.
9
10
```typescript { .api }
11
/**
12
* Base interface for all asynchronous tasks in zones
13
*/
14
interface Task {
15
/** Task type: 'microTask', 'macroTask', or 'eventTask' */
16
readonly type: TaskType;
17
18
/** Current execution state of the task */
19
state: TaskState;
20
21
/** Debug identifier indicating the API that scheduled the task */
22
readonly source: string;
23
24
/** Zone context where the task will execute */
25
readonly zone: Zone;
26
27
/** User callback function to execute */
28
callback: Function;
29
30
/** Task-specific data and configuration */
31
data?: TaskData;
32
33
/** Custom scheduler function for the task */
34
scheduleFn?: (task: Task) => void;
35
36
/** Custom cancellation function for the task */
37
cancelFn?: (task: Task) => void;
38
39
/** VM execution function (internal) */
40
invoke: Function;
41
42
/** Number of times the task has been executed */
43
runCount: number;
44
45
/** Cancel the scheduling request for this task */
46
cancelScheduleRequest(): void;
47
}
48
49
/** Task type enumeration */
50
type TaskType = 'microTask' | 'macroTask' | 'eventTask';
51
52
/** Task state enumeration */
53
type TaskState = 'notScheduled' | 'scheduling' | 'scheduled' | 'running' | 'canceling' | 'unknown';
54
```
55
56
### MicroTask
57
58
Tasks that execute immediately after the current execution stack, before yielding to the browser.
59
60
```typescript { .api }
61
/**
62
* MicroTask - executes immediately after current stack
63
* Examples: Promise.then(), queueMicrotask(), MutationObserver
64
*/
65
interface MicroTask extends Task {
66
type: 'microTask';
67
}
68
```
69
70
**Usage Examples:**
71
72
```typescript
73
import 'zone.js';
74
75
const myZone = Zone.current.fork({ name: 'micro-zone' });
76
77
// Schedule microtask directly
78
const microTask = myZone.scheduleMicroTask('custom-micro', () => {
79
console.log('MicroTask executed in:', Zone.current.name);
80
});
81
82
// Promise.then() creates microtasks automatically
83
myZone.run(() => {
84
Promise.resolve().then(() => {
85
console.log('Promise microtask in:', Zone.current.name); // 'micro-zone'
86
});
87
});
88
```
89
90
### MacroTask
91
92
Tasks that execute after a delay or in the next event loop iteration.
93
94
```typescript { .api }
95
/**
96
* MacroTask - executes after delay or in next event loop
97
* Examples: setTimeout(), setInterval(), XMLHttpRequest
98
*/
99
interface MacroTask extends Task {
100
type: 'macroTask';
101
}
102
```
103
104
**Usage Examples:**
105
106
```typescript
107
import 'zone.js';
108
109
const timerZone = Zone.current.fork({ name: 'timer-zone' });
110
111
// Schedule macrotask directly
112
const macroTask = timerZone.scheduleMacroTask(
113
'custom-timer',
114
() => console.log('MacroTask executed'),
115
{ delay: 1000 }, // TaskData with delay
116
(task) => {
117
// Custom scheduler
118
task.data.handleId = setTimeout(task.invoke, task.data.delay);
119
},
120
(task) => {
121
// Custom canceller
122
clearTimeout(task.data.handleId);
123
}
124
);
125
126
// setTimeout creates macrotasks automatically
127
timerZone.run(() => {
128
setTimeout(() => {
129
console.log('Timer macrotask in:', Zone.current.name); // 'timer-zone'
130
}, 500);
131
});
132
```
133
134
### EventTask
135
136
Tasks that handle events and may execute multiple times.
137
138
```typescript { .api }
139
/**
140
* EventTask - handles events, may execute multiple times
141
* Examples: addEventListener(), on(), once()
142
*/
143
interface EventTask extends Task {
144
type: 'eventTask';
145
}
146
```
147
148
**Usage Examples:**
149
150
```typescript
151
import 'zone.js';
152
153
const eventZone = Zone.current.fork({ name: 'event-zone' });
154
155
// Schedule event task directly
156
const eventTask = eventZone.scheduleEventTask(
157
'custom-event',
158
(event) => console.log('Event handled:', event.type),
159
{ passive: true }, // TaskData with event options
160
(task) => {
161
// Custom scheduler - add event listener
162
document.addEventListener('click', task.invoke, task.data);
163
},
164
(task) => {
165
// Custom canceller - remove event listener
166
document.removeEventListener('click', task.invoke, task.data);
167
}
168
);
169
170
// addEventListener creates event tasks automatically
171
eventZone.run(() => {
172
document.getElementById('button')?.addEventListener('click', () => {
173
console.log('Click event in:', Zone.current.name); // 'event-zone'
174
});
175
});
176
```
177
178
### TaskData Interface
179
180
Configuration data specific to different task types.
181
182
```typescript { .api }
183
/**
184
* Task-specific configuration data
185
*/
186
interface TaskData {
187
/** Whether the task repeats automatically (setInterval) */
188
isPeriodic?: boolean;
189
190
/** Whether the task can be manually rescheduled */
191
isRefreshable?: boolean;
192
193
/** Delay in milliseconds before task execution */
194
delay?: number;
195
196
/** Native handle ID (setTimeout return value) */
197
handleId?: number;
198
199
/** Generic handle for the task */
200
handle?: any;
201
202
/** Additional task-specific properties */
203
[key: string]: any;
204
}
205
```
206
207
**Usage Examples:**
208
209
```typescript
210
// Periodic task data
211
const periodicData: TaskData = {
212
isPeriodic: true,
213
delay: 1000,
214
handleId: 0
215
};
216
217
// Event task data
218
const eventData: TaskData = {
219
passive: true,
220
once: false,
221
capture: true
222
};
223
224
// Custom task data
225
const customData: TaskData = {
226
priority: 'high',
227
retries: 3,
228
timeout: 5000
229
};
230
```
231
232
### Task State Management
233
234
Tasks progress through various states during their lifecycle.
235
236
```typescript { .api }
237
/**
238
* Task execution states
239
*/
240
type TaskState =
241
| 'notScheduled' // Task created but not yet scheduled
242
| 'scheduling' // Task is being scheduled
243
| 'scheduled' // Task is scheduled and waiting to execute
244
| 'running' // Task is currently executing
245
| 'canceling' // Task is being cancelled
246
| 'unknown'; // Task state is unknown
247
248
/**
249
* Task state information for zone notifications
250
*/
251
type HasTaskState = {
252
/** Whether zone has pending microtasks */
253
microTask: boolean;
254
255
/** Whether zone has pending macrotasks */
256
macroTask: boolean;
257
258
/** Whether zone has pending event tasks */
259
eventTask: boolean;
260
261
/** Type of task that caused the state change */
262
change: TaskType;
263
};
264
```
265
266
**Usage Examples:**
267
268
```typescript
269
const taskTrackingZone = Zone.current.fork({
270
name: 'task-tracker',
271
onHasTask: (delegate, current, target, hasTaskState) => {
272
console.log('Task state changed:');
273
console.log('- MicroTasks pending:', hasTaskState.microTask);
274
console.log('- MacroTasks pending:', hasTaskState.macroTask);
275
console.log('- EventTasks pending:', hasTaskState.eventTask);
276
console.log('- Change type:', hasTaskState.change);
277
},
278
onScheduleTask: (delegate, current, target, task) => {
279
console.log(`Scheduling ${task.type}:`, task.source);
280
console.log('- Current state:', task.state);
281
return delegate.scheduleTask(target, task);
282
},
283
onInvokeTask: (delegate, current, target, task, applyThis, applyArgs) => {
284
console.log(`Executing ${task.type}:`, task.source);
285
console.log('- Run count:', task.runCount);
286
return delegate.invokeTask(target, task, applyThis, applyArgs);
287
}
288
});
289
```
290
291
### Task Scheduling Methods
292
293
Zone provides methods for directly scheduling different types of tasks.
294
295
```typescript { .api }
296
/**
297
* Schedule a MicroTask in the zone
298
* @param source - Debug identifier for the task
299
* @param callback - Function to execute
300
* @param data - Optional task configuration data
301
* @param customSchedule - Optional custom scheduler function
302
* @returns Created MicroTask
303
*/
304
scheduleMicroTask(
305
source: string,
306
callback: Function,
307
data?: TaskData,
308
customSchedule?: (task: Task) => void
309
): MicroTask;
310
311
/**
312
* Schedule a MacroTask in the zone
313
* @param source - Debug identifier for the task
314
* @param callback - Function to execute
315
* @param data - Optional task configuration data
316
* @param customSchedule - Optional custom scheduler function
317
* @param customCancel - Optional custom canceller function
318
* @returns Created MacroTask
319
*/
320
scheduleMacroTask(
321
source: string,
322
callback: Function,
323
data?: TaskData,
324
customSchedule?: (task: Task) => void,
325
customCancel?: (task: Task) => void
326
): MacroTask;
327
328
/**
329
* Schedule an EventTask in the zone
330
* @param source - Debug identifier for the task
331
* @param callback - Function to execute
332
* @param data - Optional task configuration data
333
* @param customSchedule - Optional custom scheduler function
334
* @param customCancel - Optional custom canceller function
335
* @returns Created EventTask
336
*/
337
scheduleEventTask(
338
source: string,
339
callback: Function,
340
data?: TaskData,
341
customSchedule?: (task: Task) => void,
342
customCancel?: (task: Task) => void
343
): EventTask;
344
345
/**
346
* Schedule an existing Task (useful for rescheduling cancelled tasks)
347
* @param task - Task to schedule
348
* @returns The scheduled task
349
*/
350
scheduleTask<T extends Task>(task: T): T;
351
352
/**
353
* Cancel a scheduled Task
354
* @param task - Task to cancel
355
* @returns Cancellation result
356
*/
357
cancelTask(task: Task): any;
358
```
359
360
**Usage Examples:**
361
362
```typescript
363
const schedulingZone = Zone.current.fork({ name: 'scheduler' });
364
365
// Custom microtask
366
const microTask = schedulingZone.scheduleMicroTask(
367
'custom-micro',
368
() => console.log('Custom microtask executed'),
369
{ priority: 1 }
370
);
371
372
// Custom macrotask with cancellation
373
const macroTask = schedulingZone.scheduleMacroTask(
374
'custom-macro',
375
() => console.log('Custom macrotask executed'),
376
{ delay: 2000 },
377
(task) => {
378
// Custom scheduler
379
task.data.handleId = setTimeout(() => {
380
task.invoke();
381
}, task.data.delay);
382
},
383
(task) => {
384
// Custom canceller
385
if (task.data.handleId) {
386
clearTimeout(task.data.handleId);
387
}
388
}
389
);
390
391
// Cancel the macrotask
392
setTimeout(() => {
393
schedulingZone.cancelTask(macroTask);
394
console.log('MacroTask cancelled');
395
}, 1000);
396
397
// Reschedule a task
398
const rescheduledTask = schedulingZone.scheduleTask(microTask);
399
```
400
401
### Task Lifecycle Hooks
402
403
Zone specifications can intercept task operations through lifecycle hooks.
404
405
```typescript { .api }
406
/**
407
* Hook called when tasks are scheduled
408
*/
409
onScheduleTask?: (
410
parentZoneDelegate: ZoneDelegate,
411
currentZone: Zone,
412
targetZone: Zone,
413
task: Task
414
) => Task;
415
416
/**
417
* Hook called when tasks are executed
418
*/
419
onInvokeTask?: (
420
parentZoneDelegate: ZoneDelegate,
421
currentZone: Zone,
422
targetZone: Zone,
423
task: Task,
424
applyThis: any,
425
applyArgs?: any[]
426
) => any;
427
428
/**
429
* Hook called when tasks are cancelled
430
*/
431
onCancelTask?: (
432
parentZoneDelegate: ZoneDelegate,
433
currentZone: Zone,
434
targetZone: Zone,
435
task: Task
436
) => any;
437
438
/**
439
* Hook called when zone task state changes
440
*/
441
onHasTask?: (
442
parentZoneDelegate: ZoneDelegate,
443
currentZone: Zone,
444
targetZone: Zone,
445
hasTaskState: HasTaskState
446
) => void;
447
```