Skip to content

Commit ea08231

Browse files
committed
Add a static CachedIterable.from method.
It behaves similar to the constructor. It can also detect instances of CachedSyncIterable and CachedAsyncIterable passed as the argument and if the argument's class matches the class from() was called on, it returns the argument unmodified.
1 parent e3abc35 commit ea08231

5 files changed

+69
-6
lines changed

src/cached_async_iterable.mjs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
1+
import CachedIterable from "./cached_iterable.mjs";
2+
13
/*
24
* CachedAsyncIterable caches the elements yielded by an async iterable.
35
*
46
* It can be used to iterate over an iterable many times without depleting the
57
* iterable.
68
*/
7-
export default class CachedAsyncIterable {
9+
export default class CachedAsyncIterable extends CachedIterable {
810
/**
911
* Create an `CachedAsyncIterable` instance.
1012
*
1113
* @param {Iterable} iterable
1214
* @returns {CachedAsyncIterable}
1315
*/
1416
constructor(iterable) {
17+
super();
18+
1519
if (Symbol.asyncIterator in Object(iterable)) {
1620
this.iterator = iterable[Symbol.asyncIterator]();
1721
} else if (Symbol.iterator in Object(iterable)) {
1822
this.iterator = iterable[Symbol.iterator]();
1923
} else {
2024
throw new TypeError("Argument must implement the iteration protocol.");
2125
}
22-
23-
this.seen = [];
2426
}
2527

2628
/**

src/cached_iterable.mjs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Base CachedIterable class.
3+
*/
4+
export default class CachedIterable {
5+
/**
6+
* Create an `CachedIterable` instance.
7+
*
8+
* @param {Iterable} iterable
9+
* @returns {CachedIterable}
10+
*/
11+
constructor() {
12+
this.seen = [];
13+
}
14+
15+
/**
16+
* Create a `CachedIterable` instance from an iterable or, if another
17+
* instance of `CachedIterable` is passed, return it without any
18+
* modifications.
19+
*
20+
* @param {Iterable} iterable
21+
* @returns {CachedIterable}
22+
*/
23+
static from(iterable) {
24+
if (iterable instanceof this) {
25+
return iterable;
26+
}
27+
28+
return new this(iterable);
29+
}
30+
}

src/cached_sync_iterable.mjs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
1+
import CachedIterable from "./cached_iterable.mjs";
2+
13
/*
24
* CachedSyncIterable caches the elements yielded by an iterable.
35
*
46
* It can be used to iterate over an iterable many times without depleting the
57
* iterable.
68
*/
7-
export default class CachedSyncIterable {
9+
export default class CachedSyncIterable extends CachedIterable {
810
/**
911
* Create an `CachedSyncIterable` instance.
1012
*
1113
* @param {Iterable} iterable
1214
* @returns {CachedSyncIterable}
1315
*/
1416
constructor(iterable) {
17+
super();
18+
1519
if (Symbol.iterator in Object(iterable)) {
1620
this.iterator = iterable[Symbol.iterator]();
1721
} else {
1822
throw new TypeError("Argument must implement the iteration protocol.");
1923
}
20-
21-
this.seen = [];
2224
}
2325

2426
[Symbol.iterator]() {

test/cached_async_iterable_test.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,22 @@ suite("CachedAsyncIterable", function() {
5555
});
5656
});
5757

58+
suite("from()", function() {
59+
test("pass any iterable", async function() {
60+
const iterable = CachedAsyncIterable.from([1, 2]);
61+
// No cached elements yet.
62+
assert.deepEqual([...iterable], []);
63+
// Deplete the original iterable.
64+
assert.deepEqual(await toArray(iterable), [1, 2]);
65+
});
66+
67+
test("pass another CachedAsyncIterable", function() {
68+
const iterable1 = new CachedAsyncIterable([1, 2]);
69+
const iterable2 = CachedAsyncIterable.from(iterable1);
70+
assert.equal(iterable1, iterable2);
71+
});
72+
});
73+
5874
suite("sync iteration over cached elements", function(){
5975
let o1, o2;
6076

test/cached_sync_iterable_test.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ suite("CachedSyncIterable", function() {
4040
});
4141
});
4242

43+
suite("from()", function() {
44+
test("pass any iterable", function() {
45+
const iterable = CachedSyncIterable.from([1, 2]);
46+
assert.deepEqual([...iterable], [1, 2]);
47+
});
48+
49+
test("pass another CachedSyncIterable", function() {
50+
const iterable1 = new CachedSyncIterable([1, 2]);
51+
const iterable2 = CachedSyncIterable.from(iterable1);
52+
assert.equal(iterable1, iterable2);
53+
});
54+
});
55+
4356
suite("sync iteration", function(){
4457
let o1, o2;
4558

0 commit comments

Comments
 (0)