123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721 |
- /**
- * Copyright (c) 2016, Lee Byron
- * All rights reserved.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @flow
- * @ignore
- */
- /**
- * [Iterator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterator)
- * is a *protocol* which describes a standard way to produce a sequence of
- * values, typically the values of the Iterable represented by this Iterator.
- *
- * While described by the [ES2015 version of JavaScript](http://www.ecma-international.org/ecma-262/6.0/#sec-iterator-interface)
- * it can be utilized by any version of JavaScript.
- *
- * @external Iterator
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterator|MDN Iteration protocols}
- */
- /**
- * [Iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterable)
- * is a *protocol* which when implemented allows a JavaScript object to define
- * their iteration behavior, such as what values are looped over in a
- * [`for...of`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)
- * loop or `iterall`'s `forEach` function. Many [built-in types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#Builtin_iterables)
- * implement the Iterable protocol, including `Array` and `Map`.
- *
- * While described by the [ES2015 version of JavaScript](http://www.ecma-international.org/ecma-262/6.0/#sec-iterable-interface)
- * it can be utilized by any version of JavaScript.
- *
- * @external Iterable
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#iterable|MDN Iteration protocols}
- */
- // In ES2015 environments, Symbol exists
- var SYMBOL /*: any */ = typeof Symbol === 'function' ? Symbol : void 0
- // In ES2015 (or a polyfilled) environment, this will be Symbol.iterator
- var SYMBOL_ITERATOR = SYMBOL && SYMBOL.iterator
- /**
- * A property name to be used as the name of an Iterable's method responsible
- * for producing an Iterator, referred to as `@@iterator`. Typically represents
- * the value `Symbol.iterator` but falls back to the string `"@@iterator"` when
- * `Symbol.iterator` is not defined.
- *
- * Use `$$iterator` for defining new Iterables instead of `Symbol.iterator`,
- * but do not use it for accessing existing Iterables, instead use
- * {@link getIterator} or {@link isIterable}.
- *
- * @example
- *
- * var $$iterator = require('iterall').$$iterator
- *
- * function Counter (to) {
- * this.to = to
- * }
- *
- * Counter.prototype[$$iterator] = function () {
- * return {
- * to: this.to,
- * num: 0,
- * next () {
- * if (this.num >= this.to) {
- * return { value: undefined, done: true }
- * }
- * return { value: this.num++, done: false }
- * }
- * }
- * }
- *
- * var counter = new Counter(3)
- * for (var number of counter) {
- * console.log(number) // 0 ... 1 ... 2
- * }
- *
- * @type {Symbol|string}
- */
- /*:: declare export var $$iterator: '@@iterator'; */
- export var $$iterator = SYMBOL_ITERATOR || '@@iterator'
- /**
- * Returns true if the provided object implements the Iterator protocol via
- * either implementing a `Symbol.iterator` or `"@@iterator"` method.
- *
- * @example
- *
- * var isIterable = require('iterall').isIterable
- * isIterable([ 1, 2, 3 ]) // true
- * isIterable('ABC') // true
- * isIterable({ length: 1, 0: 'Alpha' }) // false
- * isIterable({ key: 'value' }) // false
- * isIterable(new Map()) // true
- *
- * @param obj
- * A value which might implement the Iterable protocol.
- * @return {boolean} true if Iterable.
- */
- /*:: declare export function isIterable(obj: any): boolean; */
- export function isIterable(obj) {
- return !!getIteratorMethod(obj)
- }
- /**
- * Returns true if the provided object implements the Array-like protocol via
- * defining a positive-integer `length` property.
- *
- * @example
- *
- * var isArrayLike = require('iterall').isArrayLike
- * isArrayLike([ 1, 2, 3 ]) // true
- * isArrayLike('ABC') // true
- * isArrayLike({ length: 1, 0: 'Alpha' }) // true
- * isArrayLike({ key: 'value' }) // false
- * isArrayLike(new Map()) // false
- *
- * @param obj
- * A value which might implement the Array-like protocol.
- * @return {boolean} true if Array-like.
- */
- /*:: declare export function isArrayLike(obj: any): boolean; */
- export function isArrayLike(obj) {
- var length = obj != null && obj.length
- return typeof length === 'number' && length >= 0 && length % 1 === 0
- }
- /**
- * Returns true if the provided object is an Object (i.e. not a string literal)
- * and is either Iterable or Array-like.
- *
- * This may be used in place of [Array.isArray()][isArray] to determine if an
- * object should be iterated-over. It always excludes string literals and
- * includes Arrays (regardless of if it is Iterable). It also includes other
- * Array-like objects such as NodeList, TypedArray, and Buffer.
- *
- * @example
- *
- * var isCollection = require('iterall').isCollection
- * isCollection([ 1, 2, 3 ]) // true
- * isCollection('ABC') // false
- * isCollection({ length: 1, 0: 'Alpha' }) // true
- * isCollection({ key: 'value' }) // false
- * isCollection(new Map()) // true
- *
- * @example
- *
- * var forEach = require('iterall').forEach
- * if (isCollection(obj)) {
- * forEach(obj, function (value) {
- * console.log(value)
- * })
- * }
- *
- * @param obj
- * An Object value which might implement the Iterable or Array-like protocols.
- * @return {boolean} true if Iterable or Array-like Object.
- */
- /*:: declare export function isCollection(obj: any): boolean; */
- export function isCollection(obj) {
- return Object(obj) === obj && (isArrayLike(obj) || isIterable(obj))
- }
- /**
- * If the provided object implements the Iterator protocol, its Iterator object
- * is returned. Otherwise returns undefined.
- *
- * @example
- *
- * var getIterator = require('iterall').getIterator
- * var iterator = getIterator([ 1, 2, 3 ])
- * iterator.next() // { value: 1, done: false }
- * iterator.next() // { value: 2, done: false }
- * iterator.next() // { value: 3, done: false }
- * iterator.next() // { value: undefined, done: true }
- *
- * @template T the type of each iterated value
- * @param {Iterable<T>} iterable
- * An Iterable object which is the source of an Iterator.
- * @return {Iterator<T>} new Iterator instance.
- */
- /*:: declare export var getIterator:
- & (<+TValue>(iterable: Iterable<TValue>) => Iterator<TValue>)
- & ((iterable: mixed) => void | Iterator<mixed>); */
- export function getIterator(iterable) {
- var method = getIteratorMethod(iterable)
- if (method) {
- return method.call(iterable)
- }
- }
- /**
- * If the provided object implements the Iterator protocol, the method
- * responsible for producing its Iterator object is returned.
- *
- * This is used in rare cases for performance tuning. This method must be called
- * with obj as the contextual this-argument.
- *
- * @example
- *
- * var getIteratorMethod = require('iterall').getIteratorMethod
- * var myArray = [ 1, 2, 3 ]
- * var method = getIteratorMethod(myArray)
- * if (method) {
- * var iterator = method.call(myArray)
- * }
- *
- * @template T the type of each iterated value
- * @param {Iterable<T>} iterable
- * An Iterable object which defines an `@@iterator` method.
- * @return {function(): Iterator<T>} `@@iterator` method.
- */
- /*:: declare export var getIteratorMethod:
- & (<+TValue>(iterable: Iterable<TValue>) => (() => Iterator<TValue>))
- & ((iterable: mixed) => (void | (() => Iterator<mixed>))); */
- export function getIteratorMethod(iterable) {
- if (iterable != null) {
- var method =
- (SYMBOL_ITERATOR && iterable[SYMBOL_ITERATOR]) || iterable['@@iterator']
- if (typeof method === 'function') {
- return method
- }
- }
- }
- /**
- * Similar to {@link getIterator}, this method returns a new Iterator given an
- * Iterable. However it will also create an Iterator for a non-Iterable
- * Array-like collection, such as Array in a non-ES2015 environment.
- *
- * `createIterator` is complimentary to `forEach`, but allows a "pull"-based
- * iteration as opposed to `forEach`'s "push"-based iteration.
- *
- * `createIterator` produces an Iterator for Array-likes with the same behavior
- * as ArrayIteratorPrototype described in the ECMAScript specification, and
- * does *not* skip over "holes".
- *
- * @example
- *
- * var createIterator = require('iterall').createIterator
- *
- * var myArraylike = { length: 3, 0: 'Alpha', 1: 'Bravo', 2: 'Charlie' }
- * var iterator = createIterator(myArraylike)
- * iterator.next() // { value: 'Alpha', done: false }
- * iterator.next() // { value: 'Bravo', done: false }
- * iterator.next() // { value: 'Charlie', done: false }
- * iterator.next() // { value: undefined, done: true }
- *
- * @template T the type of each iterated value
- * @param {Iterable<T>|{ length: number }} collection
- * An Iterable or Array-like object to produce an Iterator.
- * @return {Iterator<T>} new Iterator instance.
- */
- /*:: declare export var createIterator:
- & (<+TValue>(collection: Iterable<TValue>) => Iterator<TValue>)
- & ((collection: {length: number}) => Iterator<mixed>)
- & ((collection: mixed) => (void | Iterator<mixed>)); */
- export function createIterator(collection) {
- if (collection != null) {
- var iterator = getIterator(collection)
- if (iterator) {
- return iterator
- }
- if (isArrayLike(collection)) {
- return new ArrayLikeIterator(collection)
- }
- }
- }
- // When the object provided to `createIterator` is not Iterable but is
- // Array-like, this simple Iterator is created.
- function ArrayLikeIterator(obj) {
- this._o = obj
- this._i = 0
- }
- // Note: all Iterators are themselves Iterable.
- ArrayLikeIterator.prototype[$$iterator] = function() {
- return this
- }
- // A simple state-machine determines the IteratorResult returned, yielding
- // each value in the Array-like object in order of their indicies.
- ArrayLikeIterator.prototype.next = function() {
- if (this._o === void 0 || this._i >= this._o.length) {
- this._o = void 0
- return { value: void 0, done: true }
- }
- return { value: this._o[this._i++], done: false }
- }
- /**
- * Given an object which either implements the Iterable protocol or is
- * Array-like, iterate over it, calling the `callback` at each iteration.
- *
- * Use `forEach` where you would expect to use a `for ... of` loop in ES6.
- * However `forEach` adheres to the behavior of [Array#forEach][] described in
- * the ECMAScript specification, skipping over "holes" in Array-likes. It will
- * also delegate to a `forEach` method on `collection` if one is defined,
- * ensuring native performance for `Arrays`.
- *
- * Similar to [Array#forEach][], the `callback` function accepts three
- * arguments, and is provided with `thisArg` as the calling context.
- *
- * Note: providing an infinite Iterator to forEach will produce an error.
- *
- * [Array#forEach]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
- *
- * @example
- *
- * var forEach = require('iterall').forEach
- *
- * forEach(myIterable, function (value, index, iterable) {
- * console.log(value, index, iterable === myIterable)
- * })
- *
- * @example
- *
- * // ES6:
- * for (let value of myIterable) {
- * console.log(value)
- * }
- *
- * // Any JavaScript environment:
- * forEach(myIterable, function (value) {
- * console.log(value)
- * })
- *
- * @template T the type of each iterated value
- * @param {Iterable<T>|{ length: number }} collection
- * The Iterable or array to iterate over.
- * @param {function(T, number, object)} callback
- * Function to execute for each iteration, taking up to three arguments
- * @param [thisArg]
- * Optional. Value to use as `this` when executing `callback`.
- */
- /*:: declare export var forEach:
- & (<+TValue, TCollection: Iterable<TValue>>(
- collection: TCollection,
- callbackFn: (value: TValue, index: number, collection: TCollection) => any,
- thisArg?: any
- ) => void)
- & (<TCollection: {length: number}>(
- collection: TCollection,
- callbackFn: (value: mixed, index: number, collection: TCollection) => any,
- thisArg?: any
- ) => void); */
- export function forEach(collection, callback, thisArg) {
- if (collection != null) {
- if (typeof collection.forEach === 'function') {
- return collection.forEach(callback, thisArg)
- }
- var i = 0
- var iterator = getIterator(collection)
- if (iterator) {
- var step
- while (!(step = iterator.next()).done) {
- callback.call(thisArg, step.value, i++, collection)
- // Infinite Iterators could cause forEach to run forever.
- // After a very large number of iterations, produce an error.
- /* istanbul ignore if */
- if (i > 9999999) {
- throw new TypeError('Near-infinite iteration.')
- }
- }
- } else if (isArrayLike(collection)) {
- for (; i < collection.length; i++) {
- if (collection.hasOwnProperty(i)) {
- callback.call(thisArg, collection[i], i, collection)
- }
- }
- }
- }
- }
- /////////////////////////////////////////////////////
- // //
- // ASYNC ITERATORS //
- // //
- /////////////////////////////////////////////////////
- /**
- * [AsyncIterable](https://tc39.github.io/proposal-async-iteration/#sec-asynciterable-interface)
- * is a *protocol* which when implemented allows a JavaScript object to define
- * an asynchronous iteration behavior, such as what values are looped over in
- * a [`for-await-of`](https://tc39.github.io/proposal-async-iteration/#sec-for-in-and-for-of-statements)
- * loop or `iterall`'s {@link forAwaitEach} function.
- *
- * While described as a proposed addition to the [ES2017 version of JavaScript](https://tc39.github.io/proposal-async-iteration/)
- * it can be utilized by any version of JavaScript.
- *
- * @external AsyncIterable
- * @see {@link https://tc39.github.io/proposal-async-iteration/#sec-asynciterable-interface|Async Iteration Proposal}
- * @template T The type of each iterated value
- * @property {function (): AsyncIterator<T>} Symbol.asyncIterator
- * A method which produces an AsyncIterator for this AsyncIterable.
- */
- /**
- * [AsyncIterator](https://tc39.github.io/proposal-async-iteration/#sec-asynciterator-interface)
- * is a *protocol* which describes a standard way to produce and consume an
- * asynchronous sequence of values, typically the values of the
- * {@link AsyncIterable} represented by this {@link AsyncIterator}.
- *
- * AsyncIterator is similar to Observable or Stream. Like an {@link Iterator} it
- * also as a `next()` method, however instead of an IteratorResult,
- * calling this method returns a {@link Promise} for a IteratorResult.
- *
- * While described as a proposed addition to the [ES2017 version of JavaScript](https://tc39.github.io/proposal-async-iteration/)
- * it can be utilized by any version of JavaScript.
- *
- * @external AsyncIterator
- * @see {@link https://tc39.github.io/proposal-async-iteration/#sec-asynciterator-interface|Async Iteration Proposal}
- */
- // In ES2017 (or a polyfilled) environment, this will be Symbol.asyncIterator
- var SYMBOL_ASYNC_ITERATOR = SYMBOL && SYMBOL.asyncIterator
- /**
- * A property name to be used as the name of an AsyncIterable's method
- * responsible for producing an Iterator, referred to as `@@asyncIterator`.
- * Typically represents the value `Symbol.asyncIterator` but falls back to the
- * string `"@@asyncIterator"` when `Symbol.asyncIterator` is not defined.
- *
- * Use `$$asyncIterator` for defining new AsyncIterables instead of
- * `Symbol.asyncIterator`, but do not use it for accessing existing Iterables,
- * instead use {@link getAsyncIterator} or {@link isAsyncIterable}.
- *
- * @example
- *
- * var $$asyncIterator = require('iterall').$$asyncIterator
- *
- * function Chirper (to) {
- * this.to = to
- * }
- *
- * Chirper.prototype[$$asyncIterator] = function () {
- * return {
- * to: this.to,
- * num: 0,
- * next () {
- * return new Promise(resolve => {
- * if (this.num >= this.to) {
- * resolve({ value: undefined, done: true })
- * } else {
- * setTimeout(() => {
- * resolve({ value: this.num++, done: false })
- * }, 1000)
- * }
- * })
- * }
- * }
- * }
- *
- * var chirper = new Chirper(3)
- * for await (var number of chirper) {
- * console.log(number) // 0 ...wait... 1 ...wait... 2
- * }
- *
- * @type {Symbol|string}
- */
- /*:: declare export var $$asyncIterator: '@@asyncIterator'; */
- export var $$asyncIterator = SYMBOL_ASYNC_ITERATOR || '@@asyncIterator'
- /**
- * Returns true if the provided object implements the AsyncIterator protocol via
- * either implementing a `Symbol.asyncIterator` or `"@@asyncIterator"` method.
- *
- * @example
- *
- * var isAsyncIterable = require('iterall').isAsyncIterable
- * isAsyncIterable(myStream) // true
- * isAsyncIterable('ABC') // false
- *
- * @param obj
- * A value which might implement the AsyncIterable protocol.
- * @return {boolean} true if AsyncIterable.
- */
- /*:: declare export function isAsyncIterable(obj: any): boolean; */
- export function isAsyncIterable(obj) {
- return !!getAsyncIteratorMethod(obj)
- }
- /**
- * If the provided object implements the AsyncIterator protocol, its
- * AsyncIterator object is returned. Otherwise returns undefined.
- *
- * @example
- *
- * var getAsyncIterator = require('iterall').getAsyncIterator
- * var asyncIterator = getAsyncIterator(myStream)
- * asyncIterator.next().then(console.log) // { value: 1, done: false }
- * asyncIterator.next().then(console.log) // { value: 2, done: false }
- * asyncIterator.next().then(console.log) // { value: 3, done: false }
- * asyncIterator.next().then(console.log) // { value: undefined, done: true }
- *
- * @template T the type of each iterated value
- * @param {AsyncIterable<T>} asyncIterable
- * An AsyncIterable object which is the source of an AsyncIterator.
- * @return {AsyncIterator<T>} new AsyncIterator instance.
- */
- /*:: declare export var getAsyncIterator:
- & (<+TValue>(asyncIterable: AsyncIterable<TValue>) => AsyncIterator<TValue>)
- & ((asyncIterable: mixed) => (void | AsyncIterator<mixed>)); */
- export function getAsyncIterator(asyncIterable) {
- var method = getAsyncIteratorMethod(asyncIterable)
- if (method) {
- return method.call(asyncIterable)
- }
- }
- /**
- * If the provided object implements the AsyncIterator protocol, the method
- * responsible for producing its AsyncIterator object is returned.
- *
- * This is used in rare cases for performance tuning. This method must be called
- * with obj as the contextual this-argument.
- *
- * @example
- *
- * var getAsyncIteratorMethod = require('iterall').getAsyncIteratorMethod
- * var method = getAsyncIteratorMethod(myStream)
- * if (method) {
- * var asyncIterator = method.call(myStream)
- * }
- *
- * @template T the type of each iterated value
- * @param {AsyncIterable<T>} asyncIterable
- * An AsyncIterable object which defines an `@@asyncIterator` method.
- * @return {function(): AsyncIterator<T>} `@@asyncIterator` method.
- */
- /*:: declare export var getAsyncIteratorMethod:
- & (<+TValue>(asyncIterable: AsyncIterable<TValue>) => (() => AsyncIterator<TValue>))
- & ((asyncIterable: mixed) => (void | (() => AsyncIterator<mixed>))); */
- export function getAsyncIteratorMethod(asyncIterable) {
- if (asyncIterable != null) {
- var method =
- (SYMBOL_ASYNC_ITERATOR && asyncIterable[SYMBOL_ASYNC_ITERATOR]) ||
- asyncIterable['@@asyncIterator']
- if (typeof method === 'function') {
- return method
- }
- }
- }
- /**
- * Similar to {@link getAsyncIterator}, this method returns a new AsyncIterator
- * given an AsyncIterable. However it will also create an AsyncIterator for a
- * non-async Iterable as well as non-Iterable Array-like collection, such as
- * Array in a pre-ES2015 environment.
- *
- * `createAsyncIterator` is complimentary to `forAwaitEach`, but allows a
- * buffering "pull"-based iteration as opposed to `forAwaitEach`'s
- * "push"-based iteration.
- *
- * `createAsyncIterator` produces an AsyncIterator for non-async Iterables as
- * described in the ECMAScript proposal [Async-from-Sync Iterator Objects](https://tc39.github.io/proposal-async-iteration/#sec-async-from-sync-iterator-objects).
- *
- * > Note: Creating `AsyncIterator`s requires the existence of `Promise`.
- * > While `Promise` has been available in modern browsers for a number of
- * > years, legacy browsers (like IE 11) may require a polyfill.
- *
- * @example
- *
- * var createAsyncIterator = require('iterall').createAsyncIterator
- *
- * var myArraylike = { length: 3, 0: 'Alpha', 1: 'Bravo', 2: 'Charlie' }
- * var iterator = createAsyncIterator(myArraylike)
- * iterator.next().then(console.log) // { value: 'Alpha', done: false }
- * iterator.next().then(console.log) // { value: 'Bravo', done: false }
- * iterator.next().then(console.log) // { value: 'Charlie', done: false }
- * iterator.next().then(console.log) // { value: undefined, done: true }
- *
- * @template T the type of each iterated value
- * @param {AsyncIterable<T>|Iterable<T>|{ length: number }} source
- * An AsyncIterable, Iterable, or Array-like object to produce an Iterator.
- * @return {AsyncIterator<T>} new AsyncIterator instance.
- */
- /*:: declare export var createAsyncIterator:
- & (<+TValue>(
- collection: Iterable<Promise<TValue> | TValue> | AsyncIterable<TValue>
- ) => AsyncIterator<TValue>)
- & ((collection: {length: number}) => AsyncIterator<mixed>)
- & ((collection: mixed) => (void | AsyncIterator<mixed>)); */
- export function createAsyncIterator(source) {
- if (source != null) {
- var asyncIterator = getAsyncIterator(source)
- if (asyncIterator) {
- return asyncIterator
- }
- var iterator = createIterator(source)
- if (iterator) {
- return new AsyncFromSyncIterator(iterator)
- }
- }
- }
- // When the object provided to `createAsyncIterator` is not AsyncIterable but is
- // sync Iterable, this simple wrapper is created.
- function AsyncFromSyncIterator(iterator) {
- this._i = iterator
- }
- // Note: all AsyncIterators are themselves AsyncIterable.
- AsyncFromSyncIterator.prototype[$$asyncIterator] = function() {
- return this
- }
- // A simple state-machine determines the IteratorResult returned, yielding
- // each value in the Array-like object in order of their indicies.
- AsyncFromSyncIterator.prototype.next = function(value) {
- return unwrapAsyncFromSync(this._i, 'next', value)
- }
- AsyncFromSyncIterator.prototype.return = function(value) {
- return this._i.return
- ? unwrapAsyncFromSync(this._i, 'return', value)
- : Promise.resolve({ value: value, done: true })
- }
- AsyncFromSyncIterator.prototype.throw = function(value) {
- return this._i.throw
- ? unwrapAsyncFromSync(this._i, 'throw', value)
- : Promise.reject(value)
- }
- function unwrapAsyncFromSync(iterator, fn, value) {
- var step
- return new Promise(function(resolve) {
- step = iterator[fn](value)
- resolve(step.value)
- }).then(function(value) {
- return { value: value, done: step.done }
- })
- }
- /**
- * Given an object which either implements the AsyncIterable protocol or is
- * Array-like, iterate over it, calling the `callback` at each iteration.
- *
- * Use `forAwaitEach` where you would expect to use a [for-await-of](https://tc39.github.io/proposal-async-iteration/#sec-for-in-and-for-of-statements) loop.
- *
- * Similar to [Array#forEach][], the `callback` function accepts three
- * arguments, and is provided with `thisArg` as the calling context.
- *
- * > Note: Using `forAwaitEach` requires the existence of `Promise`.
- * > While `Promise` has been available in modern browsers for a number of
- * > years, legacy browsers (like IE 11) may require a polyfill.
- *
- * @example
- *
- * var forAwaitEach = require('iterall').forAwaitEach
- *
- * forAwaitEach(myIterable, function (value, index, iterable) {
- * console.log(value, index, iterable === myIterable)
- * })
- *
- * @example
- *
- * // ES2017:
- * for await (let value of myAsyncIterable) {
- * console.log(await doSomethingAsync(value))
- * }
- * console.log('done')
- *
- * // Any JavaScript environment:
- * forAwaitEach(myAsyncIterable, function (value) {
- * return doSomethingAsync(value).then(console.log)
- * }).then(function () {
- * console.log('done')
- * })
- *
- * @template T the type of each iterated value
- * @param {AsyncIterable<T>|Iterable<Promise<T> | T>|{ length: number }} source
- * The AsyncIterable or array to iterate over.
- * @param {function(T, number, object)} callback
- * Function to execute for each iteration, taking up to three arguments
- * @param [thisArg]
- * Optional. Value to use as `this` when executing `callback`.
- */
- /*:: declare export var forAwaitEach:
- & (<+TValue, TCollection: Iterable<Promise<TValue> | TValue> | AsyncIterable<TValue>>(
- collection: TCollection,
- callbackFn: (value: TValue, index: number, collection: TCollection) => any,
- thisArg?: any
- ) => Promise<void>)
- & (<TCollection: { length: number }>(
- collection: TCollection,
- callbackFn: (value: mixed, index: number, collection: TCollection) => any,
- thisArg?: any
- ) => Promise<void>); */
- export function forAwaitEach(source, callback, thisArg) {
- var asyncIterator = createAsyncIterator(source)
- if (asyncIterator) {
- var i = 0
- return new Promise(function(resolve, reject) {
- function next() {
- asyncIterator
- .next()
- .then(function(step) {
- if (!step.done) {
- Promise.resolve(callback.call(thisArg, step.value, i++, source))
- .then(next)
- .catch(reject)
- } else {
- resolve()
- }
- // Explicitly return null, silencing bluebird-style warnings.
- return null
- })
- .catch(reject)
- // Explicitly return null, silencing bluebird-style warnings.
- return null
- }
- next()
- })
- }
- }
|