-
-
Notifications
You must be signed in to change notification settings - Fork 25
/
ember-concurrency.d.ts
440 lines (387 loc) · 12.7 KB
/
ember-concurrency.d.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
declare module 'ember-concurrency' {
import EmberObject from '@ember/object';
import {
UnwrapComputedPropertyGetter,
UnwrapComputedPropertyGetters
} from '@ember/object/-private/types';
import RSVP from 'rsvp';
// Lifted from @types/ember__object/observable.d.ts
interface Getter {
/**
* Retrieves the value of a property from the object.
*/
get<K extends keyof this>(key: K): UnwrapComputedPropertyGetter<this[K]>;
/**
* To get the values of multiple properties at once, call `getProperties`
* with a list of strings or an array:
*/
getProperties<K extends keyof this>(
list: K[]
): Pick<UnwrapComputedPropertyGetters<this>, K>;
getProperties<K extends keyof this>(
...list: K[]
): Pick<UnwrapComputedPropertyGetters<this>, K>;
}
export type GeneratorFn<T, Args extends any[] = any[], R = any> = (
this: T,
...args: Args
) => IterableIterator<R>;
export const all: typeof Promise.all;
export const allSettled: typeof RSVP.allSettled;
export const hash: typeof RSVP.hash;
export const race: typeof Promise.race;
export function timeout(ms: number): Promise<void>;
/**
* Use `waitForEvent` to pause the task until an event is fired.
* The event can either be a jQuery event or an `Ember.Evented` event, or any
* event system where the object supports `.on()`, `.one()` and `.off()`.
*/
export function waitForEvent(
object: EmberObject | EventTarget,
eventName: string
): Promise<Event>;
/**
* Use `waitForProperty` to pause the task until a property on an object
* changes to some expected value.
*
* This can be used for a variety of use cases, including synchronizing with
* another task by waiting for it to become idle, or change state in some
* other way.
*
* If you omit the callback, `waitForProperty` will resume execution when the
* observed property becomes truthy. If you provide a callback, it'll be
* called immediately with the observed property's current value, and multiple
* times thereafter whenever the property changes, until you return a truthy
* value from the callback, or the current task is canceled.
*
* You can also pass in a non-`function` value in place of the callback, in
* which case the task will continue executing when the property's value
* becomes the value that you passed in.
*/
export function waitForProperty<T extends object, K extends keyof T>(
object: T,
key: K,
callbackOrValue?: (value: T[K]) => boolean | any
): Promise<void>;
/**
* Use `waitForQueue` to pause the task until a certain run loop queue is
* reached.
*/
export function waitForQueue(queueName: string): Promise<void>;
export function task<Args extends any[], R>(
taskFn: GeneratorFn<unknown, Args, R>
): Task<Args, Exclude<R, Promise<any>>>;
export function task<Args extends any[], R>(encapsulatedTask: {
perform: GeneratorFn<unknown, Args, R>;
}): Task<Args, Exclude<R, Promise<any>>>;
export function taskGroup(): TaskGroupProperty;
interface CommonTaskProperty {
restartable: () => TaskProperty;
drop: () => TaskProperty;
keepLatest: () => TaskProperty;
enqueue: () => TaskProperty;
maxConcurrency: (n: number) => TaskProperty;
cancelOn: (eventName: string) => TaskProperty;
group: (groupName: string) => TaskProperty;
}
export interface TaskProperty extends CommonTaskProperty {
evented: () => TaskProperty;
debug: () => TaskProperty;
on: (eventName: string) => TaskProperty;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface TaskGroupProperty extends CommonTaskProperty {}
// Based on https://github.com/CenterForOpenScience/ember-osf-web/blob/7933316efae805e00723789809bdeb58a96a286a/types/ember-concurrency/index.d.ts
/**
* Describes the state that the task instance is in.
* Can be used for debugging, or potentially driving some UI state.
*/
export enum TaskInstanceState {
/**
* Task instance was canceled before it started.
*/
Dropped = 'dropped',
/**
* Task instance was canceled before it could finish.
*/
Canceled = 'canceled',
/**
* Task instance ran to completion, even if an exception was thrown.
*/
Finished = 'finished',
/**
* Task instance is currently running. Returns `true`, even if it is paused
* on a yielded promise.
*/
Running = 'running',
/**
* Task instance hasn't begun running yet. Usually because the task is using
* the `.enqueue()` task modifier.
*/
Waiting = 'waiting'
}
/**
* A `TaskInstance` represents a single execution of a `Task`. Every call to
* `Task#perform` returns a `TaskInstance`.
*
* `TaskInstance`s are cancelable, either explicitly via `TaskInstance#cancel`
* or `Task#cancelAll`, or automatically due to the host object being
* destroyed, or because concurrency policy enforced by a Task Modifier
* canceled the task instance.
*/
interface TaskInstanceBase<T> extends PromiseLike<T>, Getter {
/**
* Describes the state that the task instance is in.
* Can be used for debugging, or potentially driving some UI state.
*/
// readonly state: TaskInstanceState;
/**
* `true` if the task instance has started, else `false`.
*/
readonly hasStarted: boolean;
/**
* `true` if the task instance was canceled before it could run to
* completion.
*/
readonly isCanceled: boolean;
/**
* `true` if the `TaskInstance` was canceled before it could ever start
* running.
*
* For example, calling `.perform()` twice on a task with the `.drop()`
* modifier applied will result in the second task instance being dropped.
*/
readonly isDropped: boolean;
/**
* `true` if the task has run to completion.
*/
readonly isFinished: boolean;
/**
* `true` if the task is still running.
*/
readonly isRunning: boolean;
/**
* `true` if the task instance is fulfilled.
*/
readonly isSuccessful: boolean;
/**
* If this `TaskInstance` runs to completion by returning a value other than
* a rejecting promise, this property will be set with that value.
*/
readonly value?: T;
/**
* If this `TaskInstance` is canceled or throws an error (or yields a
* promise that rejects), this property will be set with that error.
*
* Otherwise, it is `null`.
*/
readonly error?: Error;
/**
* Cancels the task instance. Has no effect if the task instance has already
* been canceled or has already finished running.
*/
cancel(): void;
catch(): RSVP.Promise<unknown>;
finally(): RSVP.Promise<unknown>;
then<TResult1 = T, TResult2 = never>(
onfulfilled?:
| ((value: T) => TResult1 | RSVP.Promise<TResult1>)
| undefined
| null,
onrejected?:
| ((reason: any) => TResult2 | PromiseLike<TResult2>)
| undefined
| null
): RSVP.Promise<TResult1 | TResult2>;
}
/**
* Task instance was canceled before it started.
*/
interface InstanceDropped {
readonly state: TaskInstanceState.Dropped;
readonly hasStarted: false;
readonly isCanceled: true;
readonly isDropped: true;
readonly isFinished: false;
readonly isRunning: false;
readonly isSuccessful: false;
readonly value: undefined;
readonly error: Error;
}
/**
* Task instance was canceled before it could finish.
*/
interface InstanceCanceled {
readonly state: TaskInstanceState.Canceled;
readonly hasStarted: true;
readonly isCanceled: true;
readonly isDropped: false;
readonly isFinished: false;
readonly isRunning: false;
readonly isSuccessful: false;
readonly value: undefined;
readonly error: Error;
}
/**
* Task instance is currently running, even if it is paused on a yielded
* promise.
*/
interface InstanceRunning {
readonly state: TaskInstanceState.Running;
readonly hasStarted: true;
readonly isCanceled: false;
readonly isDropped: false;
readonly isFinished: false;
readonly isRunning: true;
readonly isSuccessful: false;
readonly value: undefined;
readonly error: null;
}
/**
* Task instance hasn't begun running yet. Usually because the task is using
* the `.enqueue()` task modifier.
*/
interface InstanceWaiting {
readonly state: TaskInstanceState.Waiting;
readonly hasStarted: false;
readonly isCanceled: false;
readonly isDropped: false;
readonly isFinished: false;
readonly isRunning: false;
readonly isSuccessful: false;
readonly value: undefined;
readonly error: null;
}
/**
* Task instance ran to completion, but an exception was thrown.
*/
interface InstanceError {
readonly state: TaskInstanceState.Finished;
readonly hasStarted: true;
readonly isCanceled: false;
readonly isDropped: false;
readonly isFinished: true;
readonly isRunning: false;
readonly isSuccessful: false;
readonly value: undefined;
readonly error: Error;
}
/**
* Task instance ran to completion successfully, without any exception being
* thrown.
*/
interface InstanceSuccess {
readonly state: TaskInstanceState.Finished;
readonly hasStarted: true;
readonly isCanceled: false;
readonly isDropped: false;
readonly isFinished: true;
readonly isRunning: false;
readonly isSuccessful: true;
readonly value: any;
readonly error: null;
}
export type TaskInstance<T> = TaskInstanceBase<T> &
(
| InstanceDropped
| InstanceCanceled
| InstanceRunning
| InstanceWaiting
| InstanceError
| InstanceSuccess);
/**
* The current state of the task.
*/
export enum TaskState {
Running = 'running',
Queued = 'queued',
Idle = 'idle'
}
/**
* The `Task` object lives on a host Ember object (e.g. a `Component`,
* `Route`, or `Controller`).
*
* You call the `.perform()` method on this object to run individual
* `TaskInstances`, and at any point, you can call the `.cancelAll()` method
* on this object to cancel all running or enqueued `TaskInstance`s.
*/
export interface Task<Args extends any[], T> extends Getter {
/**
* `true` if the task is not in the `running` or `queued` state.
*/
readonly isIdle: boolean;
/**
* `true` if any future task instances are queued.
*/
readonly isQueued: boolean;
/**
* `true` if any current task instances are running.
*/
readonly isRunning: boolean;
/**
* The most recently started task instance.
*/
readonly last?: TaskInstance<T>;
/**
* The most recently canceled task instance.
*/
readonly lastCanceled?: TaskInstance<T>;
/**
* The most recently completed task instance.
*
* This can be a successful task instance or a task instance that threw an
* error, but was *not* canceled.
*/
readonly lastComplete?: TaskInstance<T>;
/**
* The most recent task instance that errored.
*/
readonly lastErrored?: TaskInstance<T>;
/**
* The most recent task instance that is incomplete.
*
* @TODO: difference between `last`, `lastPerformed`, `lastIncomplete`?
*/
readonly lastIncomplete?: TaskInstance<T>;
/**
* The most recently performed task instance.
*/
readonly lastPerformed?: TaskInstance<T>;
/**
* The most recent task instance that is currently running.
*/
readonly lastRunning?: TaskInstance<T>;
/**
* The most recent task instance that succeeded.
*/
readonly lastSuccessful?: TaskInstance<T>;
/**
* The number of times this task has been performed.
*/
readonly performCount: number;
/**
* The current state of the task.
*
* @TODO: what is the state when `.enqueue()` is used and one `TaskInstance`
* is running, while the next is queued?
*/
readonly state: TaskState;
/**
* Creates a new `TaskInstance` and attempts to run it right away.
*
* If running this task instance would increase the task's concurrency to a
* number greater than the task's `maxConcurrency`, this task instance might
* be immediately canceled (dropped), or enqueued to run at a later time,
* after the currently running task(s) have finished.
*/
perform(...args: Args): TaskInstance<T>;
/**
* Cancels all running or queued `TaskInstance`s for this `Task`.
*
* If you're trying to cancel a specific `TaskInstance` (rather than all of
* the instances running under this task) call `.cancel()` on the specific
* `TaskInstance`.
*/
cancelAll(): void;
}
}