@thi.ng/transducers-async 0.1.2 → 0.2.1
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/CHANGELOG.md +22 -1
- package/README.md +31 -7
- package/api.d.ts +6 -0
- package/as-async.d.ts +2 -0
- package/as-async.js +11 -0
- package/delayed.d.ts +22 -0
- package/delayed.js +7 -0
- package/events.d.ts +24 -3
- package/events.js +10 -13
- package/index.d.ts +6 -0
- package/index.js +6 -0
- package/mult.d.ts +83 -0
- package/mult.js +85 -0
- package/package.json +26 -7
- package/pubsub.d.ts +26 -0
- package/pubsub.js +68 -0
- package/raf.d.ts +3 -1
- package/raf.js +17 -11
- package/range.js +2 -2
- package/repeatedly.js +2 -2
- package/sidechain.d.ts +4 -4
- package/source.d.ts +93 -0
- package/source.js +51 -0
- package/step.d.ts +2 -2
- package/step.js +1 -1
- package/sync-raf.d.ts +2 -0
- package/sync-raf.js +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
-
- **Last updated**: 2024-04-
|
|
3
|
+
- **Last updated**: 2024-04-22T09:56:21Z
|
|
4
4
|
- **Generator**: [thi.ng/monopub](https://thi.ng/monopub)
|
|
5
5
|
|
|
6
6
|
All notable changes to this project will be documented in this file.
|
|
@@ -9,6 +9,27 @@ See [Conventional Commits](https://conventionalcommits.org/) for commit guidelin
|
|
|
9
9
|
**Note:** Unlisted _patch_ versions only involve non-code or otherwise excluded changes
|
|
10
10
|
and/or version bumps of transitive dependencies.
|
|
11
11
|
|
|
12
|
+
## [0.2.0](https://github.com/thi-ng/umbrella/tree/@thi.ng/transducers-async@0.2.0) (2024-04-20)
|
|
13
|
+
|
|
14
|
+
#### 🚀 Features
|
|
15
|
+
|
|
16
|
+
- add delayed() & wait() helpers ([d2f0738](https://github.com/thi-ng/umbrella/commit/d2f0738))
|
|
17
|
+
- add mult() for 1:N splitting (multiple subscribers) ([ad1b63b](https://github.com/thi-ng/umbrella/commit/ad1b63b))
|
|
18
|
+
- add asAsyncIterable() helper ([8e40424](https://github.com/thi-ng/umbrella/commit/8e40424))
|
|
19
|
+
- add source(), refactor events() ([b94d150](https://github.com/thi-ng/umbrella/commit/b94d150))
|
|
20
|
+
- add syncRAF(), update sidechain() args ([54ded8b](https://github.com/thi-ng/umbrella/commit/54ded8b))
|
|
21
|
+
- add pubsub() ([1f406d0](https://github.com/thi-ng/umbrella/commit/1f406d0))
|
|
22
|
+
- update/extend Source interface/impl ([a95819b](https://github.com/thi-ng/umbrella/commit/a95819b))
|
|
23
|
+
- add [@thi.ng/buffers](https://github.com/thi-ng/umbrella/tree/main/packages/buffers) support for source() ([c46d862](https://github.com/thi-ng/umbrella/commit/c46d862))
|
|
24
|
+
- update Source API, add docs ([7a7b5ab](https://github.com/thi-ng/umbrella/commit/7a7b5ab))
|
|
25
|
+
|
|
26
|
+
#### ♻️ Refactoring
|
|
27
|
+
|
|
28
|
+
- add ClosableAsyncGenerator type, update events() & source() ([929d860](https://github.com/thi-ng/umbrella/commit/929d860))
|
|
29
|
+
- simplify raf() impl ([38c36b9](https://github.com/thi-ng/umbrella/commit/38c36b9))
|
|
30
|
+
- rewrite to use source()
|
|
31
|
+
- update type usage ([bec044c](https://github.com/thi-ng/umbrella/commit/bec044c))
|
|
32
|
+
|
|
12
33
|
### [0.1.1](https://github.com/thi-ng/umbrella/tree/@thi.ng/transducers-async@0.1.1) (2024-04-11)
|
|
13
34
|
|
|
14
35
|
#### ♻️ Refactoring
|
package/README.md
CHANGED
|
@@ -16,12 +16,14 @@
|
|
|
16
16
|
|
|
17
17
|
- [About](#about)
|
|
18
18
|
- [Evaluators](#evaluators)
|
|
19
|
-
- [
|
|
19
|
+
- [Generators & iterators](#generators--iterators)
|
|
20
|
+
- [Combinators](#combinators)
|
|
20
21
|
- [Transducers](#transducers)
|
|
21
22
|
- [Reducers](#reducers)
|
|
22
23
|
- [Status](#status)
|
|
23
24
|
- [Installation](#installation)
|
|
24
25
|
- [Dependencies](#dependencies)
|
|
26
|
+
- [Usage examples](#usage-examples)
|
|
25
27
|
- [API](#api)
|
|
26
28
|
- [Authors](#authors)
|
|
27
29
|
- [License](#license)
|
|
@@ -38,18 +40,26 @@ Async versions of various highly composable transducers, reducers and iterators.
|
|
|
38
40
|
- [`step()`](https://docs.thi.ng/umbrella/transducers-async/functions/step.html)
|
|
39
41
|
- [`transduce()`](https://docs.thi.ng/umbrella/transducers-async/functions/transduce.html)
|
|
40
42
|
|
|
41
|
-
###
|
|
43
|
+
### Generators & iterators
|
|
42
44
|
|
|
45
|
+
- [`asAsyncIterable()`](https://docs.thi.ng/umbrella/transducers-async/functions/asAsyncIterable.html)
|
|
43
46
|
- [`concat()`](https://docs.thi.ng/umbrella/transducers-async/functions/concat.html)
|
|
44
47
|
- [`events()`](https://docs.thi.ng/umbrella/transducers-async/functions/events.html)
|
|
45
|
-
- [`merge()`](https://docs.thi.ng/umbrella/transducers-async/functions/merge.html)
|
|
46
48
|
- [`raf()`](https://docs.thi.ng/umbrella/transducers-async/functions/raf.html)
|
|
47
49
|
- [`range()`](https://docs.thi.ng/umbrella/transducers-async/functions/range.html)
|
|
48
50
|
- [`repeatedly()`](https://docs.thi.ng/umbrella/transducers-async/functions/repeatedly.html)
|
|
49
51
|
- [`sidechain()`](https://docs.thi.ng/umbrella/transducers-async/functions/sidechain.html)
|
|
50
|
-
- [`
|
|
52
|
+
- [`source()`](https://docs.thi.ng/umbrella/transducers-async/functions/source.html)
|
|
51
53
|
- [`zip()`](https://docs.thi.ng/umbrella/transducers-async/functions/zip.html)
|
|
52
54
|
|
|
55
|
+
### Combinators
|
|
56
|
+
|
|
57
|
+
- [`merge()`](https://docs.thi.ng/umbrella/transducers-async/functions/merge.html)
|
|
58
|
+
- [`mult()`](https://docs.thi.ng/umbrella/transducers-async/functions/mult.html)
|
|
59
|
+
- [`pubsub()`](https://docs.thi.ng/umbrella/transducers-async/functions/pubsub.html)
|
|
60
|
+
- [`sync()`](https://docs.thi.ng/umbrella/transducers-async/functions/sync.html)
|
|
61
|
+
- [`syncRAF()`](https://docs.thi.ng/umbrella/transducers-async/functions/syncRAF.html)
|
|
62
|
+
|
|
53
63
|
### Transducers
|
|
54
64
|
|
|
55
65
|
- [`comp()`](https://docs.thi.ng/umbrella/transducers-async/functions/comp.html)
|
|
@@ -58,6 +68,7 @@ Async versions of various highly composable transducers, reducers and iterators.
|
|
|
58
68
|
- [`mapcat()`](https://docs.thi.ng/umbrella/transducers-async/functions/mapcat.html)
|
|
59
69
|
- [`multiplex()`](https://docs.thi.ng/umbrella/transducers-async/functions/multiplex.html)
|
|
60
70
|
- [`multiplexObj()`](https://docs.thi.ng/umbrella/transducers-async/functions/multiplexObj.html)
|
|
71
|
+
- [`partition()`](https://docs.thi.ng/umbrella/transducers-async/functions/partition.html)
|
|
61
72
|
- [`take()`](https://docs.thi.ng/umbrella/transducers-async/functions/take.html)
|
|
62
73
|
- [`throttle()`](https://docs.thi.ng/umbrella/transducers-async/functions/throttle.html)
|
|
63
74
|
- [`throttleTime()`](https://docs.thi.ng/umbrella/transducers-async/functions/throttleTime.html)
|
|
@@ -87,10 +98,10 @@ import * as txa from "@thi.ng/transducers-async";
|
|
|
87
98
|
Browser ESM import:
|
|
88
99
|
|
|
89
100
|
```html
|
|
90
|
-
<script type="module" src="https://
|
|
101
|
+
<script type="module" src="https://esm.run/@thi.ng/transducers-async"></script>
|
|
91
102
|
```
|
|
92
103
|
|
|
93
|
-
[
|
|
104
|
+
[JSDelivr documentation](https://www.jsdelivr.com/)
|
|
94
105
|
|
|
95
106
|
For Node.js REPL:
|
|
96
107
|
|
|
@@ -98,20 +109,33 @@ For Node.js REPL:
|
|
|
98
109
|
const txa = await import("@thi.ng/transducers-async");
|
|
99
110
|
```
|
|
100
111
|
|
|
101
|
-
Package sizes (brotli'd, pre-treeshake): ESM:
|
|
112
|
+
Package sizes (brotli'd, pre-treeshake): ESM: 3.10 KB
|
|
102
113
|
|
|
103
114
|
## Dependencies
|
|
104
115
|
|
|
105
116
|
- [@thi.ng/api](https://github.com/thi-ng/umbrella/tree/develop/packages/api)
|
|
117
|
+
- [@thi.ng/buffers](https://github.com/thi-ng/umbrella/tree/develop/packages/buffers)
|
|
106
118
|
- [@thi.ng/checks](https://github.com/thi-ng/umbrella/tree/develop/packages/checks)
|
|
107
119
|
- [@thi.ng/compose](https://github.com/thi-ng/umbrella/tree/develop/packages/compose)
|
|
108
120
|
- [@thi.ng/errors](https://github.com/thi-ng/umbrella/tree/develop/packages/errors)
|
|
109
121
|
- [@thi.ng/transducers](https://github.com/thi-ng/umbrella/tree/develop/packages/transducers)
|
|
110
122
|
|
|
123
|
+
## Usage examples
|
|
124
|
+
|
|
125
|
+
One project in this repo's
|
|
126
|
+
[/examples](https://github.com/thi-ng/umbrella/tree/develop/examples)
|
|
127
|
+
directory is using this package:
|
|
128
|
+
|
|
129
|
+
| Description | Live demo | Source |
|
|
130
|
+
|:----------------------------------------------------------|:-------------------------------------------------|:------------------------------------------------------------------------------|
|
|
131
|
+
| Basic & barebones usage of async iterables in thi.ng/rdom | [Demo](https://demo.thi.ng/umbrella/rdom-async/) | [Source](https://github.com/thi-ng/umbrella/tree/develop/examples/rdom-async) |
|
|
132
|
+
|
|
111
133
|
## API
|
|
112
134
|
|
|
113
135
|
[Generated API docs](https://docs.thi.ng/umbrella/transducers-async/)
|
|
114
136
|
|
|
137
|
+
TODO
|
|
138
|
+
|
|
115
139
|
## Authors
|
|
116
140
|
|
|
117
141
|
- [Karsten Schmidt](https://thi.ng)
|
package/api.d.ts
CHANGED
|
@@ -20,4 +20,10 @@ export type AsyncMultiplexTxLike<A, B> = AsyncTxLike<A, B> | [AsyncTxLike<A, B>,
|
|
|
20
20
|
export interface IXformAsync<A, B> {
|
|
21
21
|
xformAsync(): AsyncTransducer<A, B>;
|
|
22
22
|
}
|
|
23
|
+
export interface ClosableAsyncGenerator<T> extends AsyncGenerator<T> {
|
|
24
|
+
/**
|
|
25
|
+
* Terminates the iterable at the next opportunity.
|
|
26
|
+
*/
|
|
27
|
+
close(): void;
|
|
28
|
+
}
|
|
23
29
|
//# sourceMappingURL=api.d.ts.map
|
package/as-async.d.ts
ADDED
package/as-async.js
ADDED
package/delayed.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Same as [thi.ng/compose `delayed()`](). Re-exported for convenience. Yields
|
|
3
|
+
* `x` as promise which only resolves after `delay` milliseconds.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* Also see {@link wait}.
|
|
7
|
+
*
|
|
8
|
+
* @param x
|
|
9
|
+
* @param delay
|
|
10
|
+
*/
|
|
11
|
+
export declare const delayed: <T>(x: T, t: number) => Promise<T>;
|
|
12
|
+
/**
|
|
13
|
+
* Syntax sugar for {@link delayed}, yields a void promise which resolves after
|
|
14
|
+
* `delay` milliseconds.
|
|
15
|
+
*
|
|
16
|
+
* @remarks
|
|
17
|
+
* Also see {@link delayed}.
|
|
18
|
+
*
|
|
19
|
+
* @param delay
|
|
20
|
+
*/
|
|
21
|
+
export declare const wait: (delay: number) => Promise<void>;
|
|
22
|
+
//# sourceMappingURL=delayed.d.ts.map
|
package/delayed.js
ADDED
package/events.d.ts
CHANGED
|
@@ -1,14 +1,35 @@
|
|
|
1
|
+
import type { IDeref, Maybe } from "@thi.ng/api";
|
|
2
|
+
import type { ClosableAsyncGenerator } from "./api.js";
|
|
1
3
|
/**
|
|
2
4
|
* Attaches an event listener to given `target` and yields an async iterator of
|
|
3
5
|
* events.
|
|
4
6
|
*
|
|
5
7
|
* @remarks
|
|
6
|
-
* The event listener can be removed (and the iterator stopped) by
|
|
7
|
-
*
|
|
8
|
+
* The event listener can be removed (and the iterator stopped) by calling
|
|
9
|
+
* `.close()`.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts tangle:../export/events.ts
|
|
13
|
+
* import { events, map, run } from "@thi.ng/transducers-async";
|
|
14
|
+
*
|
|
15
|
+
* const resize = events(window, "resize");
|
|
16
|
+
*
|
|
17
|
+
* const sizes = map(
|
|
18
|
+
* (e) => [window.innerWidth, window.innerHeight],
|
|
19
|
+
* resize
|
|
20
|
+
* );
|
|
21
|
+
*
|
|
22
|
+
* for await (let [w, h] of sizes) {
|
|
23
|
+
* console.log(w, h)
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* // to stop listening and stop iterator
|
|
27
|
+
* resize.close();
|
|
28
|
+
* ```
|
|
8
29
|
*
|
|
9
30
|
* @param target
|
|
10
31
|
* @param id
|
|
11
32
|
* @param opts
|
|
12
33
|
*/
|
|
13
|
-
export declare
|
|
34
|
+
export declare const events: <T extends Event = Event>(target: EventTarget, id: string, opts?: EventListenerOptions) => ClosableAsyncGenerator<T> & IDeref<Maybe<T>>;
|
|
14
35
|
//# sourceMappingURL=events.d.ts.map
|
package/events.js
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const listener = (e) =>
|
|
1
|
+
import { source } from "./source.js";
|
|
2
|
+
const events = (target, id, opts) => {
|
|
3
|
+
const listener = (e) => gen.write(e);
|
|
4
4
|
target.addEventListener(id, listener, opts);
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
13
|
-
target.removeEventListener(id, listener, opts);
|
|
14
|
-
}
|
|
5
|
+
const gen = source();
|
|
6
|
+
gen.close = () => {
|
|
7
|
+
target.removeEventListener(id, listener, opts);
|
|
8
|
+
gen.write(void 0);
|
|
9
|
+
};
|
|
10
|
+
return gen;
|
|
11
|
+
};
|
|
15
12
|
export {
|
|
16
13
|
events
|
|
17
14
|
};
|
package/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from "./api.js";
|
|
2
|
+
export * from "./as-async.js";
|
|
2
3
|
export * from "./cat.js";
|
|
3
4
|
export * from "./comp.js";
|
|
4
5
|
export * from "./compr.js";
|
|
5
6
|
export * from "./concat.js";
|
|
7
|
+
export * from "./delayed.js";
|
|
6
8
|
export * from "./ensure.js";
|
|
7
9
|
export * from "./events.js";
|
|
8
10
|
export * from "./filter.js";
|
|
@@ -10,9 +12,11 @@ export * from "./iterator.js";
|
|
|
10
12
|
export * from "./map.js";
|
|
11
13
|
export * from "./mapcat.js";
|
|
12
14
|
export * from "./merge.js";
|
|
15
|
+
export * from "./mult.js";
|
|
13
16
|
export * from "./multiplex-obj.js";
|
|
14
17
|
export * from "./multiplex.js";
|
|
15
18
|
export * from "./partition.js";
|
|
19
|
+
export * from "./pubsub.js";
|
|
16
20
|
export * from "./push.js";
|
|
17
21
|
export * from "./raf.js";
|
|
18
22
|
export * from "./range.js";
|
|
@@ -20,8 +24,10 @@ export * from "./reduce.js";
|
|
|
20
24
|
export * from "./repeatedly.js";
|
|
21
25
|
export * from "./run.js";
|
|
22
26
|
export * from "./sidechain.js";
|
|
27
|
+
export * from "./source.js";
|
|
23
28
|
export * from "./step.js";
|
|
24
29
|
export * from "./sync.js";
|
|
30
|
+
export * from "./sync-raf.js";
|
|
25
31
|
export * from "./take.js";
|
|
26
32
|
export * from "./throttle-time.js";
|
|
27
33
|
export * from "./throttle.js";
|
package/index.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export * from "./api.js";
|
|
2
|
+
export * from "./as-async.js";
|
|
2
3
|
export * from "./cat.js";
|
|
3
4
|
export * from "./comp.js";
|
|
4
5
|
export * from "./compr.js";
|
|
5
6
|
export * from "./concat.js";
|
|
7
|
+
export * from "./delayed.js";
|
|
6
8
|
export * from "./ensure.js";
|
|
7
9
|
export * from "./events.js";
|
|
8
10
|
export * from "./filter.js";
|
|
@@ -10,9 +12,11 @@ export * from "./iterator.js";
|
|
|
10
12
|
export * from "./map.js";
|
|
11
13
|
export * from "./mapcat.js";
|
|
12
14
|
export * from "./merge.js";
|
|
15
|
+
export * from "./mult.js";
|
|
13
16
|
export * from "./multiplex-obj.js";
|
|
14
17
|
export * from "./multiplex.js";
|
|
15
18
|
export * from "./partition.js";
|
|
19
|
+
export * from "./pubsub.js";
|
|
16
20
|
export * from "./push.js";
|
|
17
21
|
export * from "./raf.js";
|
|
18
22
|
export * from "./range.js";
|
|
@@ -20,8 +24,10 @@ export * from "./reduce.js";
|
|
|
20
24
|
export * from "./repeatedly.js";
|
|
21
25
|
export * from "./run.js";
|
|
22
26
|
export * from "./sidechain.js";
|
|
27
|
+
export * from "./source.js";
|
|
23
28
|
export * from "./step.js";
|
|
24
29
|
export * from "./sync.js";
|
|
30
|
+
export * from "./sync-raf.js";
|
|
25
31
|
export * from "./take.js";
|
|
26
32
|
export * from "./throttle-time.js";
|
|
27
33
|
export * from "./throttle.js";
|
package/mult.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Fn, Fn0, Maybe } from "@thi.ng/api";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a new {@link Mult} instance which allows splitting a single `src`
|
|
4
|
+
* async iterable into multiple parallel subscribers. Iteration only starts when
|
|
5
|
+
* the first subscriber is attached (via {@link Mult.subscribe}) and back
|
|
6
|
+
* pressure is handled by waiting for **all** child subscribers to deliver their
|
|
7
|
+
* values before the next value from `src` is consumed. `Mult` allows dynamic
|
|
8
|
+
* subscriptions and unsubscriptions and will stop consuming from `src` when no
|
|
9
|
+
* further subscribers are attached.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts tangle:../export/mult.ts
|
|
13
|
+
* import { map, mult, run, wait } from "@thi.ng/transducers-async";
|
|
14
|
+
*
|
|
15
|
+
* const root = mult(
|
|
16
|
+
* (async function* () {
|
|
17
|
+
* yield "hello";
|
|
18
|
+
* await wait(1000);
|
|
19
|
+
* yield "world";
|
|
20
|
+
* await wait(1000);
|
|
21
|
+
* yield "good bye";
|
|
22
|
+
* })()
|
|
23
|
+
* );
|
|
24
|
+
*
|
|
25
|
+
* // 1st subscriber (vanilla JS)
|
|
26
|
+
* (async () => {
|
|
27
|
+
* for await (let x of root.subscribe()) console.log("vanilla:", x);
|
|
28
|
+
* })();
|
|
29
|
+
*
|
|
30
|
+
* // 2nd subscriber (transducer), attached with delay
|
|
31
|
+
* setTimeout(
|
|
32
|
+
* () =>
|
|
33
|
+
* run(
|
|
34
|
+
* map(async (x) => {
|
|
35
|
+
* console.log("tx", x);
|
|
36
|
+
* await wait(1500);
|
|
37
|
+
* }),
|
|
38
|
+
* root.subscribe()
|
|
39
|
+
* ),
|
|
40
|
+
* 900
|
|
41
|
+
* );
|
|
42
|
+
*
|
|
43
|
+
* // vanilla: hello
|
|
44
|
+
* // vanilla: world
|
|
45
|
+
* // tx world
|
|
46
|
+
* // vanilla: good bye
|
|
47
|
+
* // tx good bye
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* @param src
|
|
51
|
+
*/
|
|
52
|
+
export declare const mult: <T>(src: AsyncIterable<T>) => Mult<T>;
|
|
53
|
+
export declare class Mult<T> {
|
|
54
|
+
src: AsyncIterable<T>;
|
|
55
|
+
protected subs: MSub<T>[];
|
|
56
|
+
protected isActive: boolean;
|
|
57
|
+
constructor(src: AsyncIterable<T>);
|
|
58
|
+
/**
|
|
59
|
+
* Creates a new subscription (aka custom `AsyncIterable`) which will
|
|
60
|
+
* receive any future values from `src`. The returned subscription can be
|
|
61
|
+
* removed again via {@link Mult.unsubscribe}.
|
|
62
|
+
*/
|
|
63
|
+
subscribe(): AsyncIterable<T>;
|
|
64
|
+
/**
|
|
65
|
+
* Attempts to remove given child subscription (presumably created via
|
|
66
|
+
* {@link Mult.subscribe}). Returns true if removal was successful.
|
|
67
|
+
*
|
|
68
|
+
* @param sub
|
|
69
|
+
*/
|
|
70
|
+
unsubscribe(sub: AsyncIterable<T>): boolean;
|
|
71
|
+
}
|
|
72
|
+
/** @internal */
|
|
73
|
+
export declare class MSub<T> {
|
|
74
|
+
valueP: Promise<Maybe<T>>;
|
|
75
|
+
notifyP: Promise<void>;
|
|
76
|
+
resolve: Fn<Maybe<T>, void>;
|
|
77
|
+
notify: Fn0<void>;
|
|
78
|
+
active: boolean;
|
|
79
|
+
constructor();
|
|
80
|
+
[Symbol.asyncIterator](): AsyncGenerator<Awaited<Awaited<T> & null> | Awaited<Awaited<T> & {}>, void, unknown>;
|
|
81
|
+
protected $await(): void;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=mult.d.ts.map
|
package/mult.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { illegalState } from "@thi.ng/errors/illegal-state";
|
|
2
|
+
const mult = (src) => new Mult(src);
|
|
3
|
+
class Mult {
|
|
4
|
+
constructor(src) {
|
|
5
|
+
this.src = src;
|
|
6
|
+
}
|
|
7
|
+
subs = [];
|
|
8
|
+
isActive = false;
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new subscription (aka custom `AsyncIterable`) which will
|
|
11
|
+
* receive any future values from `src`. The returned subscription can be
|
|
12
|
+
* removed again via {@link Mult.unsubscribe}.
|
|
13
|
+
*/
|
|
14
|
+
subscribe() {
|
|
15
|
+
const sub = new MSub();
|
|
16
|
+
this.subs.push(sub);
|
|
17
|
+
if (!this.isActive) {
|
|
18
|
+
this.isActive = true;
|
|
19
|
+
(async () => {
|
|
20
|
+
for await (let val of this.src) {
|
|
21
|
+
for (let s of this.subs)
|
|
22
|
+
s.resolve(val);
|
|
23
|
+
if (val === void 0)
|
|
24
|
+
this.subs.length = 0;
|
|
25
|
+
if (!this.subs.length)
|
|
26
|
+
break;
|
|
27
|
+
await Promise.all(this.subs.map((x) => x.notifyP));
|
|
28
|
+
}
|
|
29
|
+
for (let s of this.subs)
|
|
30
|
+
s.resolve(void 0);
|
|
31
|
+
this.subs.length = 0;
|
|
32
|
+
this.isActive = false;
|
|
33
|
+
})();
|
|
34
|
+
}
|
|
35
|
+
return sub;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Attempts to remove given child subscription (presumably created via
|
|
39
|
+
* {@link Mult.subscribe}). Returns true if removal was successful.
|
|
40
|
+
*
|
|
41
|
+
* @param sub
|
|
42
|
+
*/
|
|
43
|
+
unsubscribe(sub) {
|
|
44
|
+
const idx = this.subs.findIndex((x) => x === sub);
|
|
45
|
+
if (idx >= 0) {
|
|
46
|
+
this.subs.splice(idx, 1);
|
|
47
|
+
sub.resolve(void 0);
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
class MSub {
|
|
54
|
+
valueP;
|
|
55
|
+
notifyP;
|
|
56
|
+
resolve;
|
|
57
|
+
notify;
|
|
58
|
+
active = false;
|
|
59
|
+
constructor() {
|
|
60
|
+
this.$await();
|
|
61
|
+
}
|
|
62
|
+
async *[Symbol.asyncIterator]() {
|
|
63
|
+
if (this.active)
|
|
64
|
+
illegalState("multiple consumers unsupported");
|
|
65
|
+
this.active = true;
|
|
66
|
+
while (true) {
|
|
67
|
+
const res = await this.valueP;
|
|
68
|
+
if (res === void 0)
|
|
69
|
+
break;
|
|
70
|
+
yield res;
|
|
71
|
+
this.notify();
|
|
72
|
+
this.$await();
|
|
73
|
+
}
|
|
74
|
+
this.active = false;
|
|
75
|
+
}
|
|
76
|
+
$await() {
|
|
77
|
+
this.notifyP = new Promise((res) => this.notify = res);
|
|
78
|
+
this.valueP = new Promise((res) => this.resolve = res);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export {
|
|
82
|
+
MSub,
|
|
83
|
+
Mult,
|
|
84
|
+
mult
|
|
85
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thi.ng/transducers-async",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Async versions of various highly composable transducers, reducers and iterators",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "./index.js",
|
|
@@ -36,11 +36,12 @@
|
|
|
36
36
|
"tool:tangle": "../../node_modules/.bin/tangle src/**/*.ts"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@thi.ng/api": "^8.
|
|
40
|
-
"@thi.ng/
|
|
41
|
-
"@thi.ng/
|
|
42
|
-
"@thi.ng/
|
|
43
|
-
"@thi.ng/
|
|
39
|
+
"@thi.ng/api": "^8.11.0",
|
|
40
|
+
"@thi.ng/buffers": "^0.1.1",
|
|
41
|
+
"@thi.ng/checks": "^3.6.2",
|
|
42
|
+
"@thi.ng/compose": "^3.0.2",
|
|
43
|
+
"@thi.ng/errors": "^2.5.5",
|
|
44
|
+
"@thi.ng/transducers": "^9.0.2"
|
|
44
45
|
},
|
|
45
46
|
"devDependencies": {
|
|
46
47
|
"@microsoft/api-extractor": "^7.43.0",
|
|
@@ -89,6 +90,9 @@
|
|
|
89
90
|
"./api": {
|
|
90
91
|
"default": "./api.js"
|
|
91
92
|
},
|
|
93
|
+
"./as-async": {
|
|
94
|
+
"default": "./as-async.js"
|
|
95
|
+
},
|
|
92
96
|
"./cat": {
|
|
93
97
|
"default": "./cat.js"
|
|
94
98
|
},
|
|
@@ -101,6 +105,9 @@
|
|
|
101
105
|
"./concat": {
|
|
102
106
|
"default": "./concat.js"
|
|
103
107
|
},
|
|
108
|
+
"./delayed": {
|
|
109
|
+
"default": "./delayed.js"
|
|
110
|
+
},
|
|
104
111
|
"./ensure": {
|
|
105
112
|
"default": "./ensure.js"
|
|
106
113
|
},
|
|
@@ -122,6 +129,9 @@
|
|
|
122
129
|
"./merge": {
|
|
123
130
|
"default": "./merge.js"
|
|
124
131
|
},
|
|
132
|
+
"./mult": {
|
|
133
|
+
"default": "./mult.js"
|
|
134
|
+
},
|
|
125
135
|
"./multiplex-obj": {
|
|
126
136
|
"default": "./multiplex-obj.js"
|
|
127
137
|
},
|
|
@@ -131,6 +141,9 @@
|
|
|
131
141
|
"./partition": {
|
|
132
142
|
"default": "./partition.js"
|
|
133
143
|
},
|
|
144
|
+
"./pubsub": {
|
|
145
|
+
"default": "./pubsub.js"
|
|
146
|
+
},
|
|
134
147
|
"./push": {
|
|
135
148
|
"default": "./push.js"
|
|
136
149
|
},
|
|
@@ -152,9 +165,15 @@
|
|
|
152
165
|
"./sidechain": {
|
|
153
166
|
"default": "./sidechain.js"
|
|
154
167
|
},
|
|
168
|
+
"./source": {
|
|
169
|
+
"default": "./source.js"
|
|
170
|
+
},
|
|
155
171
|
"./step": {
|
|
156
172
|
"default": "./step.js"
|
|
157
173
|
},
|
|
174
|
+
"./sync-raf": {
|
|
175
|
+
"default": "./sync-raf.js"
|
|
176
|
+
},
|
|
158
177
|
"./sync": {
|
|
159
178
|
"default": "./sync.js"
|
|
160
179
|
},
|
|
@@ -180,5 +199,5 @@
|
|
|
180
199
|
"status": "alpha",
|
|
181
200
|
"year": 2018
|
|
182
201
|
},
|
|
183
|
-
"gitHead": "
|
|
202
|
+
"gitHead": "4e2bf6b12e35192e678b525fa699429370e357d3\n"
|
|
184
203
|
}
|
package/pubsub.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Fn } from "@thi.ng/api";
|
|
2
|
+
import { MSub } from "./mult.js";
|
|
3
|
+
export declare const pubsub: <K, V>(src: AsyncIterable<V>, topicFn: Fn<V, K>) => PubSub<K, V>;
|
|
4
|
+
export declare class PubSub<K, V> {
|
|
5
|
+
src: AsyncIterable<V>;
|
|
6
|
+
topicFn: Fn<V, K>;
|
|
7
|
+
protected topics: Map<K, MSub<V>[]>;
|
|
8
|
+
protected isActive: boolean;
|
|
9
|
+
constructor(src: AsyncIterable<V>, topicFn: Fn<V, K>);
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new subscription (aka custom `AsyncIterable`) which will
|
|
12
|
+
* receive any future values from `src` matching given topic `id`. The
|
|
13
|
+
* returned subscription can be removed again via
|
|
14
|
+
* {@link PubSub.unsubscribeTopic}.
|
|
15
|
+
*/
|
|
16
|
+
subscribeTopic(id: K): AsyncIterable<V>;
|
|
17
|
+
/**
|
|
18
|
+
* Attempts to remove given child subscription (presumably created via
|
|
19
|
+
* {@link PubSub.subscribeTopic}). Returns true if removal was successful.
|
|
20
|
+
*
|
|
21
|
+
* @param sub
|
|
22
|
+
*/
|
|
23
|
+
unsubscribeTopic(id: K, sub: AsyncIterable<V>): boolean;
|
|
24
|
+
protected process(): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=pubsub.d.ts.map
|
package/pubsub.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { MSub } from "./mult.js";
|
|
2
|
+
const pubsub = (src, topicFn) => new PubSub(src, topicFn);
|
|
3
|
+
class PubSub {
|
|
4
|
+
constructor(src, topicFn) {
|
|
5
|
+
this.src = src;
|
|
6
|
+
this.topicFn = topicFn;
|
|
7
|
+
}
|
|
8
|
+
topics = /* @__PURE__ */ new Map();
|
|
9
|
+
isActive = false;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new subscription (aka custom `AsyncIterable`) which will
|
|
12
|
+
* receive any future values from `src` matching given topic `id`. The
|
|
13
|
+
* returned subscription can be removed again via
|
|
14
|
+
* {@link PubSub.unsubscribeTopic}.
|
|
15
|
+
*/
|
|
16
|
+
subscribeTopic(id) {
|
|
17
|
+
const sub = new MSub();
|
|
18
|
+
let subs = this.topics.get(id);
|
|
19
|
+
if (!subs) {
|
|
20
|
+
this.topics.set(id, subs = []);
|
|
21
|
+
}
|
|
22
|
+
subs.push(sub);
|
|
23
|
+
if (!this.isActive) {
|
|
24
|
+
this.isActive = true;
|
|
25
|
+
this.process();
|
|
26
|
+
}
|
|
27
|
+
return sub;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Attempts to remove given child subscription (presumably created via
|
|
31
|
+
* {@link PubSub.subscribeTopic}). Returns true if removal was successful.
|
|
32
|
+
*
|
|
33
|
+
* @param sub
|
|
34
|
+
*/
|
|
35
|
+
unsubscribeTopic(id, sub) {
|
|
36
|
+
const subs = this.topics.get(id);
|
|
37
|
+
if (!subs)
|
|
38
|
+
return false;
|
|
39
|
+
const idx = subs.findIndex((x) => x === sub) ?? -1;
|
|
40
|
+
if (idx >= 0) {
|
|
41
|
+
subs.splice(idx, 1);
|
|
42
|
+
sub.resolve(void 0);
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
async process() {
|
|
48
|
+
for await (let val of this.src) {
|
|
49
|
+
const topic = this.topicFn(val);
|
|
50
|
+
const subs = this.topics.get(topic);
|
|
51
|
+
if (!(subs && subs.length))
|
|
52
|
+
continue;
|
|
53
|
+
for (let s of subs)
|
|
54
|
+
s.resolve(val);
|
|
55
|
+
await Promise.all(subs.map((x) => x.notifyP));
|
|
56
|
+
}
|
|
57
|
+
for (let subs of this.topics.values()) {
|
|
58
|
+
for (let s of subs)
|
|
59
|
+
s.resolve(void 0);
|
|
60
|
+
}
|
|
61
|
+
this.topics.clear();
|
|
62
|
+
this.isActive = false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
PubSub,
|
|
67
|
+
pubsub
|
|
68
|
+
};
|
package/raf.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { IDeref, Maybe } from "@thi.ng/api";
|
|
2
|
+
import type { ClosableAsyncGenerator } from "./api.js";
|
|
1
3
|
export interface RAFOpts {
|
|
2
4
|
/**
|
|
3
5
|
* If true (default: false), passes the timestamps received
|
|
@@ -16,5 +18,5 @@ export interface RAFOpts {
|
|
|
16
18
|
*/
|
|
17
19
|
t0: number | boolean;
|
|
18
20
|
}
|
|
19
|
-
export declare
|
|
21
|
+
export declare const raf: (opts?: Partial<RAFOpts>) => ClosableAsyncGenerator<number> & IDeref<Maybe<number>>;
|
|
20
22
|
//# sourceMappingURL=raf.d.ts.map
|
package/raf.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import { source } from "./source.js";
|
|
2
|
+
const raf = (opts) => {
|
|
2
3
|
let frame = 0;
|
|
3
4
|
let t0 = opts?.t0 || 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
let isClosed = false;
|
|
6
|
+
const gen = source();
|
|
7
|
+
gen.close = () => {
|
|
8
|
+
isClosed = true;
|
|
9
|
+
gen.write(void 0);
|
|
10
|
+
};
|
|
11
|
+
const update = (t) => {
|
|
12
|
+
if (isClosed)
|
|
13
|
+
return;
|
|
9
14
|
if (opts?.timestamp) {
|
|
10
15
|
if (t0 === true)
|
|
11
16
|
t0 = t;
|
|
@@ -14,11 +19,12 @@ async function* raf(opts) {
|
|
|
14
19
|
} else {
|
|
15
20
|
t = frame++;
|
|
16
21
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
gen.write(t);
|
|
23
|
+
requestAnimationFrame(update);
|
|
24
|
+
};
|
|
25
|
+
requestAnimationFrame(update);
|
|
26
|
+
return gen;
|
|
27
|
+
};
|
|
22
28
|
export {
|
|
23
29
|
raf
|
|
24
30
|
};
|
package/range.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { delayed } from "@thi.ng/compose/delayed";
|
|
2
1
|
import { Range } from "@thi.ng/transducers/range";
|
|
2
|
+
import { wait } from "./delayed.js";
|
|
3
3
|
async function* range(...args) {
|
|
4
4
|
const delay = args.pop();
|
|
5
5
|
for (let x of new Range(...args)) {
|
|
6
6
|
yield x;
|
|
7
|
-
await
|
|
7
|
+
await wait(delay);
|
|
8
8
|
}
|
|
9
9
|
}
|
|
10
10
|
export {
|
package/repeatedly.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { wait } from "./delayed.js";
|
|
2
2
|
async function* repeatedly(fn, n = Infinity, delay = 0) {
|
|
3
3
|
for (let i = 0; i < n; i++) {
|
|
4
4
|
yield await fn(i);
|
|
5
5
|
if (delay > 0) {
|
|
6
|
-
await
|
|
6
|
+
await wait(delay);
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
}
|
package/sidechain.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
export interface SidechainOpts {
|
|
2
2
|
/**
|
|
3
3
|
* If true (default), only emits the last received value when the sidechain
|
|
4
|
-
*
|
|
5
|
-
* last time the sidechain triggered.
|
|
4
|
+
* delivers a truthy value. Otherwise buffers and emits *all* received
|
|
5
|
+
* values since the last time the sidechain triggered.
|
|
6
6
|
*
|
|
7
7
|
* @defaultValue true
|
|
8
8
|
*/
|
|
9
9
|
lastOnly: boolean;
|
|
10
10
|
}
|
|
11
|
-
export declare function sidechain<T>(src: AsyncIterable<T>, side: AsyncIterable<
|
|
11
|
+
export declare function sidechain<T>(src: AsyncIterable<T>, side: AsyncIterable<any>, opts: Partial<SidechainOpts> & {
|
|
12
12
|
lastOnly: false;
|
|
13
13
|
}): AsyncIterableIterator<T[]>;
|
|
14
|
-
export declare function sidechain<T>(src: AsyncIterable<T>, side: AsyncIterable<
|
|
14
|
+
export declare function sidechain<T>(src: AsyncIterable<T>, side: AsyncIterable<any>, opts?: Partial<SidechainOpts>): AsyncIterableIterator<T>;
|
|
15
15
|
//# sourceMappingURL=sidechain.d.ts.map
|
package/source.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { FnO, IDeref, Maybe } from "@thi.ng/api";
|
|
2
|
+
import type { IReadWriteBuffer } from "@thi.ng/buffers";
|
|
3
|
+
import type { ClosableAsyncGenerator } from "./api.js";
|
|
4
|
+
export interface Source<T> extends ClosableAsyncGenerator<T>, IDeref<Maybe<T>> {
|
|
5
|
+
/**
|
|
6
|
+
* Writes or queues given value `x` to be asynchronously passed down to the
|
|
7
|
+
* source's consumer. If no other values are queued yet, the source
|
|
8
|
+
* processes it immediately, otherwise the value will be first added to the
|
|
9
|
+
* source's configured buffer.
|
|
10
|
+
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* Once {@link Source.close} has been called, all future write attempts will
|
|
13
|
+
* be silently ignored.
|
|
14
|
+
*
|
|
15
|
+
* @param x
|
|
16
|
+
*/
|
|
17
|
+
write(x?: T): void;
|
|
18
|
+
/**
|
|
19
|
+
* Returns the most recently produced/yielded value (if any). If there's
|
|
20
|
+
* back pressure (i.e. queued values caused by more frequent writes and than
|
|
21
|
+
* reads, the returned value is **not** necessarily the last value written
|
|
22
|
+
* via {@link Source.write}). Returns `undefined`, if no value has yet been
|
|
23
|
+
* written or the source has already been fully closed (via
|
|
24
|
+
* {@link Source.close}).
|
|
25
|
+
*/
|
|
26
|
+
deref(): Maybe<T>;
|
|
27
|
+
/**
|
|
28
|
+
* Takes a function which will be called with the most recent emitted value
|
|
29
|
+
* of the source (plus any optionally given args) and queues the result of
|
|
30
|
+
* that function as new value to be asynchronously passed down by the source
|
|
31
|
+
* to its consumer.
|
|
32
|
+
*
|
|
33
|
+
* @remarks
|
|
34
|
+
* Only use this function in situations where there's no back pressure (i.e.
|
|
35
|
+
* no queued up values).
|
|
36
|
+
*
|
|
37
|
+
* @param fn
|
|
38
|
+
* @param args
|
|
39
|
+
*/
|
|
40
|
+
update(fn: FnO<Maybe<T>, Maybe<T>>, ...args: any[]): void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Creates an async iterable acting as data source with an extended API to
|
|
44
|
+
* externally feed/write new values, which are then passed downstream to any
|
|
45
|
+
* attached processors/transducers. The source can use an optional buffer
|
|
46
|
+
* implementation to control back pressure behavior and value ordering.
|
|
47
|
+
*
|
|
48
|
+
* @remarks
|
|
49
|
+
* See [thi.ng/buffers](https://thi.ng/buffers) for available buffer
|
|
50
|
+
* implementations. By default a
|
|
51
|
+
* [`fifo()`](https://docs.thi.ng/umbrella/buffers/functions/fifo.html) buffer
|
|
52
|
+
* with capacity=1 is used.
|
|
53
|
+
*
|
|
54
|
+
* If `initial` is given, the source will immediately deliver this value once a
|
|
55
|
+
* consumer is attached.
|
|
56
|
+
*
|
|
57
|
+
* The `source()` stores the last produced/yielded value (not necessarily the
|
|
58
|
+
* last value written via {@link Source.write}), which can be read via
|
|
59
|
+
* {@link Source.deref} or updated via {@link Source.update}.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts tangle:../export/source.ts
|
|
63
|
+
* import { source, map, run } from "@thi.ng/transducers-async";
|
|
64
|
+
*
|
|
65
|
+
* // create empty source
|
|
66
|
+
* const src = source();
|
|
67
|
+
*
|
|
68
|
+
* // create an async consumer
|
|
69
|
+
* // (consumer stops when we close the source)
|
|
70
|
+
* run(
|
|
71
|
+
* map(async (x) => x * 10),
|
|
72
|
+
* (x) => console.log("result:", x),
|
|
73
|
+
* src
|
|
74
|
+
* )
|
|
75
|
+
*
|
|
76
|
+
* // set new value
|
|
77
|
+
* src.write(23);
|
|
78
|
+
* // result: 230
|
|
79
|
+
*
|
|
80
|
+
* // update last value
|
|
81
|
+
* // (delayed invocation here to avoid buffer overflow)
|
|
82
|
+
* setTimeout(() => src.update((x) => x + 1), 0);
|
|
83
|
+
* // result: 240
|
|
84
|
+
*
|
|
85
|
+
* // close/terminate source
|
|
86
|
+
* setTimeout(() => src.close(), 0);
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @param initial
|
|
90
|
+
* @param buffer
|
|
91
|
+
*/
|
|
92
|
+
export declare const source: <T>(initial?: T, buffer?: IReadWriteBuffer<Maybe<T>> | number) => Source<T>;
|
|
93
|
+
//# sourceMappingURL=source.d.ts.map
|
package/source.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { fifo } from "@thi.ng/buffers/fifo";
|
|
2
|
+
import { isNumber } from "@thi.ng/checks/is-number";
|
|
3
|
+
import { illegalState } from "@thi.ng/errors/illegal-state";
|
|
4
|
+
const source = (initial, buffer = 1) => {
|
|
5
|
+
const queue = isNumber(buffer) ? fifo(buffer) : buffer;
|
|
6
|
+
let last = initial;
|
|
7
|
+
let state = 0;
|
|
8
|
+
let promise;
|
|
9
|
+
let resolve;
|
|
10
|
+
const newPromise = () => {
|
|
11
|
+
promise = new Promise(($resolve) => {
|
|
12
|
+
resolve = $resolve;
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
newPromise();
|
|
16
|
+
const gen = async function* () {
|
|
17
|
+
while (true) {
|
|
18
|
+
const val = await promise;
|
|
19
|
+
last = val;
|
|
20
|
+
if (val === void 0)
|
|
21
|
+
break;
|
|
22
|
+
yield val;
|
|
23
|
+
newPromise();
|
|
24
|
+
if (queue.readable())
|
|
25
|
+
resolve(queue.read());
|
|
26
|
+
}
|
|
27
|
+
state = 2;
|
|
28
|
+
}();
|
|
29
|
+
gen.write = (x) => {
|
|
30
|
+
if (state > 0)
|
|
31
|
+
return;
|
|
32
|
+
if (resolve) {
|
|
33
|
+
resolve(x);
|
|
34
|
+
resolve = void 0;
|
|
35
|
+
} else if (queue.writable()) {
|
|
36
|
+
queue.write(x);
|
|
37
|
+
if (x === void 0)
|
|
38
|
+
state = 1;
|
|
39
|
+
} else
|
|
40
|
+
illegalState("buffer overflow");
|
|
41
|
+
};
|
|
42
|
+
gen.update = (fn, ...args) => gen.write(fn(last, ...args));
|
|
43
|
+
gen.close = () => gen.write(void 0);
|
|
44
|
+
gen.deref = () => last;
|
|
45
|
+
if (initial !== void 0)
|
|
46
|
+
gen.write(initial);
|
|
47
|
+
return gen;
|
|
48
|
+
};
|
|
49
|
+
export {
|
|
50
|
+
source
|
|
51
|
+
};
|
package/step.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Fn } from "@thi.ng/api";
|
|
1
|
+
import type { Fn, Maybe } from "@thi.ng/api";
|
|
2
2
|
import type { AsyncTxLike } from "./api.js";
|
|
3
|
-
export declare const step: <A, B>(tx: AsyncTxLike<A, B>, unwrap?: boolean) => Fn<A, Promise<B | B[]
|
|
3
|
+
export declare const step: <A, B>(tx: AsyncTxLike<A, B>, unwrap?: boolean) => Fn<A, Promise<Maybe<B | B[]>>>;
|
|
4
4
|
//# sourceMappingURL=step.d.ts.map
|
package/step.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { isReduced } from "@thi.ng/transducers/reduced";
|
|
1
2
|
import { ensureAsyncTransducer } from "./ensure.js";
|
|
2
3
|
import { push } from "./push.js";
|
|
3
|
-
import { isReduced } from "@thi.ng/transducers/reduced";
|
|
4
4
|
const step = (tx, unwrap = true) => {
|
|
5
5
|
const [_, complete, reduce] = ensureAsyncTransducer(tx)(push());
|
|
6
6
|
let done = false;
|
package/sync-raf.d.ts
ADDED