-
Notifications
You must be signed in to change notification settings - Fork 3
/
job.js
85 lines (79 loc) · 2.09 KB
/
job.js
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
// @ts-nocheck
/**
* @module shared
*/
/**
* Start parallelized work that can be canceled at a later time.
*
* @param {W} asyncWork
* @returns {R}
* @template T
* @template {AriaATCIShared.JobWork<T>} W
* @template {AriaATCIShared.Job<T>} R
*/
export function startJob(asyncWork) {
let completed = null;
let cancel = null;
let canceled = false;
const cancelToken = new Promise(resolve => {
cancel = () => {
canceled = true;
resolve({ done: true });
return completed;
};
});
const privateSignal = {
cancelable(iterable) {
return {
[Symbol.asyncIterator]() {
if (canceled) {
return {
async next() {
return { done: true };
},
};
}
const iterator = iterable[Symbol.asyncIterator]();
return {
async next() {
return await Promise.race([
(async () => {
// If this promise never resolves, this wrapped iterable may
// not be cancelable. Depending on how its implemented there
// isn't an interface from here to stop what it is trying to
// do.
const next = await iterator.next();
if (canceled) {
if (iterator.return) {
await iterator.return();
}
return { done: true };
}
return next;
})(),
cancelToken,
]);
},
async throw(error) {
if (iterator.throw) {
return await iterator.throw(error);
}
throw error;
},
async return(value) {
if (iterator.return) {
return await iterator.return(value);
}
return { value, done: true };
},
};
},
};
},
};
const publicSignal = {
cancel,
};
completed = asyncWork(privateSignal);
return publicSignal;
}