Skip to content

Commit

Permalink
Add support for async iterables.
Browse files Browse the repository at this point in the history
This is now possible thanks to the work in #682.
  • Loading branch information
vqvu committed Jul 7, 2019
1 parent 97397c1 commit 67eee6e
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 6 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ this library.

### New additions
* `takeWhile` - returns a new stream that ends when the function passed as a parameter stops returning true.
[#677](https://github.com/caolan/highland/pull/677)
[#677](https://github.com/caolan/highland/pull/677).
* Async Iterator/Iterable support - Taks an object that is a async iterator or
iterable as defined by the [Async Iteration
specs](https://tc39.es/proposal-async-iteration/).
[#682](https://github.com/caolan/highland/pull/682).

3.0.0-beta.9
-----
Expand Down
35 changes: 30 additions & 5 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,12 @@ function bindContext(fn, context) {
* iterator's done value returns true. If the iterator's `next()` method throws or rejects, the exception will be emitted as an error,
* and the stream will be ended with no further calls to `next()`.
*
* **Asynchronous Iterable -** Accepts an object with a `Symbol.asyncIterator`
* property that conforms to the [async iteration
* spec](https://github.com/tc39/proposal-async-iteration#async-iterators-and-async-iterables).
* The constructor will create a async iterator and use it to generator emitted
* values.
*
* @id _(source)
* @section Stream Objects
* @name _(source)
Expand Down Expand Up @@ -199,15 +205,30 @@ function bindContext(fn, context) {
* // from a Promise object
* var foo = _($.getJSON('/api/foo'));
*
* //from an iterator
* // from an iterator
* var map = new Map([['a', 1], ['b', 2]]);
* var bar = _(map.values()).toArray(_.log);
* //=> [1, 2]
*
* //from an iterable
* // from an iterable
* var set = new Set([1, 2, 2, 3, 4]);
* var bar = _(set).toArray(_.log);
* //=> [ 1, 2, 3, 4]
* //=> [1, 2, 3, 4]
*
* // from an async iterator
* async function* generator() {
* yield 1;
* yield 2;
* }
* var stream = _(generator()).toArray(_.log);
* //=> [1, 2]
*
* // from an async iterable
* var asyncIterable = {
* [Symbol.asyncIterable]: generator
* };
* var stream = _(asyncIterable).toArray(_.log);
* //=> [1, 2]
*/

/*eslint-disable no-multi-spaces */
Expand Down Expand Up @@ -259,13 +280,17 @@ function __(StreamCtor) {
// their Symbol.iterator method returns the `this` object
// and an infinite loop would result otherwise
else if (_.isFunction(xs.next)) {
//probably an iterator
// probably an iterator. This handle both sync and async iterators.
return iteratorStream(StreamCtor, xs);
}
else if (!_.isUndefined(_global.Symbol) && xs[_global.Symbol.iterator]) {
//probably an iterable
// probably an iterable
return iteratorStream(StreamCtor, xs[_global.Symbol.iterator]());
}
else if (!_.isUndefined(_global.Symbol) && xs[_global.Symbol.asyncIterator]) {
// probably an async iterable
return iteratorStream(StreamCtor, xs[_global.Symbol.asyncIterator]());
}
else {
throw new Error(
'Object was not a stream, promise, iterator or iterable: ' + (typeof xs)
Expand Down
10 changes: 10 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1333,6 +1333,16 @@ exports.constructor = {
},
};

// Async iterable tests
if (global.Symbol && global.Symbol.asyncIterator) {
exports.constructor['from async iterable'] = function (test) {
var asyncIterable = {};
asyncIterable[global.Symbol.asyncIterator] =
this.createTestAsyncIterator.bind(this, [1, 2, 3]);
_(asyncIterable).toArray(this.tester([1, 2, 3], test));
};
}

exports.GeneratorStream = {
'sync next does not re-enter generator': function (test) {
test.expect(2);
Expand Down

0 comments on commit 67eee6e

Please sign in to comment.