Minimal zero-dependency utilities for using JavaScript Iterables in all environments.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Asynchronous iteration functionality for working with AsyncIterables, Promise-containing Iterables, and Array-like objects. These utilities enable consistent async iteration patterns across all JavaScript environments, including those without native async iteration support.
Symbol used as the property name for async iterator methods. Represents Symbol.asyncIterator when available, falls back to "@@asyncIterator" for environments without async iteration support.
/**
* Property name for async iterator method, used for creating new AsyncIterables
* @type {Symbol|string}
*/
export const $$asyncIterator: unique symbol;Usage Example:
import { $$asyncIterator } from "iterall";
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);
}
});
}
};
};
const chirper = new Chirper(3);
for await (const number of chirper) {
console.log(number); // 0 ...wait... 1 ...wait... 2
}Tests if an object implements the AsyncIterator protocol via Symbol.asyncIterator or "@@asyncIterator" method.
/**
* Tests if object implements AsyncIterator protocol
* @param obj - Value to test for AsyncIterable protocol
* @returns true if object is AsyncIterable
*/
function isAsyncIterable(obj: any): obj is AsyncIterable<any>;Usage Examples:
import { isAsyncIterable } from "iterall";
// Custom async iterable
const asyncGenerator = async function* () {
yield 1;
yield 2;
yield 3;
};
isAsyncIterable(asyncGenerator()); // true - Async generators are async iterable
isAsyncIterable([1, 2, 3]); // false - Arrays are not async iterable
isAsyncIterable("ABC"); // false - Strings are not async iterable
// Check before using async iteration
if (isAsyncIterable(myStream)) {
for await (const item of myStream) {
console.log(item);
}
}Returns the AsyncIterator object if the provided object implements the AsyncIterator protocol, otherwise returns undefined.
/**
* Gets AsyncIterator from an AsyncIterable object
* @param asyncIterable - AsyncIterable object to get AsyncIterator from
* @returns AsyncIterator instance or undefined
*/
function getAsyncIterator<TValue>(asyncIterable: AsyncIterable<TValue>): AsyncIterator<TValue>;
function getAsyncIterator(asyncIterable: any): void | AsyncIterator<any>;Usage Example:
import { getAsyncIterator } from "iterall";
const asyncIterator = getAsyncIterator(myAsyncStream);
if (asyncIterator) {
const result1 = await asyncIterator.next(); // { value: ..., done: false }
const result2 = await asyncIterator.next(); // { value: ..., done: false }
const result3 = await asyncIterator.next(); // { value: undefined, done: true }
}Returns the method responsible for producing the AsyncIterator object. Used for performance tuning in rare cases.
/**
* Gets the @@asyncIterator method from an AsyncIterable object
* @param asyncIterable - AsyncIterable object with @@asyncIterator method
* @returns @@asyncIterator method or undefined
*/
function getAsyncIteratorMethod<TValue>(asyncIterable: AsyncIterable<TValue>): () => AsyncIterator<TValue>;
function getAsyncIteratorMethod(asyncIterable: any): void | (() => AsyncIterator<any>);Usage Example:
import { getAsyncIteratorMethod } from "iterall";
const method = getAsyncIteratorMethod(myAsyncStream);
if (method) {
const asyncIterator = method.call(myAsyncStream);
const result = await asyncIterator.next();
}Creates an AsyncIterator for AsyncIterables, Iterables containing Promises, and Array-like collections. Provides universal AsyncIterator creation with automatic sync-to-async wrapping.
/**
* Creates AsyncIterator from various source types
* @param source - AsyncIterable, Iterable with Promises, or Array-like object
* @returns AsyncIterator instance or undefined
*/
function createAsyncIterator<TValue>(
collection: AsyncIterable<TValue> | Iterable<Promise<TValue> | TValue>
): AsyncIterator<TValue>;
function createAsyncIterator(collection: { length: number }): AsyncIterator<any>;
function createAsyncIterator(collection: any): void | AsyncIterator<any>;Usage Examples:
import { createAsyncIterator } from "iterall";
// Works with AsyncIterables
const asyncIterator = createAsyncIterator(myAsyncStream);
// Works with Iterables containing Promises
const promiseArray = [
Promise.resolve("first"),
Promise.resolve("second"),
Promise.resolve("third")
];
const promiseIterator = createAsyncIterator(promiseArray);
// Works with Array-like objects
const arrayLike = { length: 3, 0: "Alpha", 1: "Bravo", 2: "Charlie" };
const arrayLikeAsyncIterator = createAsyncIterator(arrayLike);
if (arrayLikeAsyncIterator) {
const result1 = await arrayLikeAsyncIterator.next(); // { value: "Alpha", done: false }
const result2 = await arrayLikeAsyncIterator.next(); // { value: "Bravo", done: false }
const result3 = await arrayLikeAsyncIterator.next(); // { value: "Charlie", done: false }
const result4 = await arrayLikeAsyncIterator.next(); // { value: undefined, done: true }
}
// Mixed sync/async values
const mixedIterable = [1, Promise.resolve(2), 3];
const mixedIterator = createAsyncIterator(mixedIterable);
// Handles both immediate values and promises consistentlyAsynchronously iterates over AsyncIterables, Promise-containing Iterables, or Array-like collections, calling a callback at each iteration. Equivalent to for-await-of loops but works in any JavaScript environment.
/**
* Asynchronously iterates over collection, calling callback for each item
* @param source - AsyncIterable, Iterable with Promises, or Array-like object
* @param callbackFn - Function called for each item (value, index, collection)
* @param thisArg - Optional value to use as 'this' in callback
* @returns Promise that resolves when iteration completes
*/
function forAwaitEach<TCollection extends AsyncIterable<any>>(
collection: TCollection,
callbackFn: (value: ResolvedOf<TCollection>, index: number, collection: TCollection) => any,
thisArg?: any
): Promise<void>;
function forAwaitEach<TCollection extends Iterable<any>>(
collection: TCollection,
callbackFn: (value: ResolvedOf<TCollection>, index: number, collection: TCollection) => any,
thisArg?: any
): Promise<void>;
function forAwaitEach<TCollection extends { length: number }>(
collection: TCollection,
callbackFn: (value: any, index: number, collection: TCollection) => any,
thisArg?: any
): Promise<void>;Usage Examples:
import { forAwaitEach } from "iterall";
// Basic async iteration
await forAwaitEach(myAsyncStream, async (value, index) => {
const processed = await processValue(value);
console.log(`Item ${index}:`, processed);
});
// Works with Promise arrays
const promiseArray = [
fetch("/api/user/1").then(r => r.json()),
fetch("/api/user/2").then(r => r.json()),
fetch("/api/user/3").then(r => r.json())
];
await forAwaitEach(promiseArray, (user, index) => {
console.log(`User ${index}:`, user.name);
});
// Mixed sync/async processing
await forAwaitEach([1, 2, 3], async (number) => {
if (number % 2 === 0) {
const result = await heavyAsyncOperation(number);
console.log("Async result:", result);
} else {
console.log("Sync result:", number * 2);
}
});
// Using thisArg
const processor = {
prefix: "Processed: ",
async processItem(value) {
return this.prefix + value;
}
};
await forAwaitEach([1, 2, 3], async function(value) {
const result = await this.processItem(value);
console.log(result);
}, processor);Error Handling:
import { forAwaitEach } from "iterall";
try {
await forAwaitEach(myAsyncData, async (item) => {
if (item.shouldFail) {
throw new Error("Processing failed");
}
return processItem(item);
});
} catch (error) {
console.error("Iteration failed:", error);
}Performance Notes:
Promise.all() with regular iterationPromise support (polyfill needed for IE11 and older)Comparison with Native Syntax:
// Native for-await-of (ES2018+)
for await (const value of myAsyncIterable) {
console.log(await doSomethingAsync(value));
}
console.log("done");
// Equivalent using forAwaitEach (works in any environment)
await forAwaitEach(myAsyncIterable, async (value) => {
console.log(await doSomethingAsync(value));
});
console.log("done");