1 | import { AsyncIterableX } from './asynciterablex';
|
2 | async function forEach(source, fn) {
|
3 | for await (const item of source) {
|
4 | await fn(item);
|
5 | }
|
6 | }
|
7 | export class DebounceAsyncIterable extends AsyncIterableX {
|
8 | constructor(source, time) {
|
9 | super();
|
10 | this._source = source;
|
11 | this._time = time;
|
12 | }
|
13 | async *[Symbol.asyncIterator]() {
|
14 | let noValue;
|
15 | let lastItem;
|
16 | let deferred;
|
17 | let resolver;
|
18 | let done = false;
|
19 | let hasError = false;
|
20 | let error;
|
21 | const reset = (hasNoValue) => {
|
22 | noValue = hasNoValue;
|
23 | lastItem = undefined;
|
24 | deferred = new Promise(r => (resolver = r));
|
25 | };
|
26 | const run = () => {
|
27 | if (lastItem === undefined) {
|
28 | noValue = true;
|
29 | return;
|
30 | }
|
31 | const item = lastItem;
|
32 | const res = resolver;
|
33 | reset(false);
|
34 | setTimeout(run, this._time);
|
35 | res(item);
|
36 | };
|
37 | reset(true);
|
38 | forEach(this._source, item => {
|
39 | lastItem = item;
|
40 | if (noValue) {
|
41 | run();
|
42 | }
|
43 | })
|
44 | .then(() => (done = true))
|
45 | .catch(err => {
|
46 | hasError = true;
|
47 | error = err;
|
48 | });
|
49 | while (1) {
|
50 | if (done) {
|
51 | break;
|
52 | }
|
53 | if (hasError) {
|
54 | throw error;
|
55 | }
|
56 | yield await deferred;
|
57 | }
|
58 | }
|
59 | }
|
60 | export function debounce(source, time) {
|
61 | return new DebounceAsyncIterable(source, time);
|
62 | }
|
63 |
|
64 |
|