Skip to content

Commit 3a21ed0

Browse files
committed
async generators working in channels
1 parent 8c2cefe commit 3a21ed0

File tree

4 files changed

+331
-126
lines changed

4 files changed

+331
-126
lines changed

packages/channels/channels.js

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,77 @@
1+
import { Multicast } from './generators.js';
12

23
export function use(asyncSource, ...args) {
3-
const [transforms, options] = processArguments(args);
4+
const [channels, options] = getArguments(args);
45
const type = typeof asyncSource;
56

67
switch(true) {
78
case asyncSource instanceof Promise:
8-
return transforms.length < 2
9-
? [fromPromise(asyncSource, transforms[0], options)]
10-
: branchPromise(asyncSource, transforms, options);
9+
return channels.length < 2
10+
? [fromPromise(asyncSource, channels[0], options)]
11+
: branchPromise(asyncSource, channels, options);
12+
case !!asyncSource[Symbol.asyncIterator]:
13+
return channels.length < 2
14+
? [fromAsyncIterator(asyncSource, channels[0], options)]
15+
: branchAsyncIterator(asyncSource, channels, options);
1116
default:
1217
throwAsyncSourceTypeError(type);
1318
}
1419
}
1520

16-
function fromPromise(promise, transform, options) {
21+
function getArguments(channels) {
22+
let options = null;
23+
if(channels.length) {
24+
const maybeOptions = channels.at(-1);
25+
if(typeof maybeOptions === 'object') {
26+
options = maybeOptions;
27+
channels.length--;
28+
}
29+
}
30+
return [channels, options];
31+
}
32+
33+
function fromPromise(promise, channel, options) {
1734
const startWith = options?.startWith;
1835
if(startWith) {
19-
return fromPromiseStartWith(promise, transform, startWith);
36+
return fromPromiseStartWith(promise, channel, startWith);
37+
}
38+
return [channel ? promise.then(channel) : promise];
39+
}
40+
41+
async function* fromPromiseStartWith(promise, channel, startWith) {
42+
yield startWith;
43+
yield channel ? promise.then(channel) : promise;
44+
}
45+
46+
async function* fromAsyncIterator(iterator, channel, options) {
47+
const startWith = options?.startWith;
48+
if(startWith) yield startWith;
49+
for await(const value of iterator) {
50+
yield channel ? channel(value) : value;
2051
}
21-
return [transform ? promise.then(transform) : promise];
2252
}
2353

24-
function branchPromise(promise, transforms) {
25-
return transforms.map(transform => {
26-
if(Array.isArray(transform)) { // [transform, options]
27-
return fromPromise(promise, transform[0], transform[1]);
54+
function branchPromise(promise, channels) {
55+
return channels.map(channel => {
56+
if(Array.isArray(channel)) { // [channel, options]
57+
return fromPromise(promise, channel[0], channel[1]);
2858
}
29-
return promise.then(transform);
59+
return promise.then(channel);
3060
});
3161
}
3262

33-
async function* fromPromiseStartWith(promise, transform, startWith) {
34-
yield startWith;
35-
yield transform ? promise.then(transform) : promise;
63+
function branchAsyncIterator(iterator, channels, options) {
64+
const multicast = new Multicast(iterator);
65+
return channels.map(channel => {
66+
if(Array.isArray(channel)) { // [channel, options]
67+
return multicast.subscriber(channel[0], channel[1]);
68+
}
69+
return multicast.subscriber(channel, options);
70+
});
3671
}
3772

3873
function throwAsyncSourceTypeError(type) {
3974
throw new TypeError(`\
4075
Unexpected asynchronous data source type "${type}". Expected an async data provider type, or \
4176
a function that returns an async data provider type."`);
4277
}
43-
44-
function processArguments(transforms) {
45-
let options = null;
46-
if(transforms.length) {
47-
const maybeOptions = transforms.at(-1);
48-
if(typeof maybeOptions === 'object') {
49-
options = maybeOptions;
50-
transforms.length--;
51-
}
52-
}
53-
return [transforms, options];
54-
}

0 commit comments

Comments
 (0)