0
# AsyncIterator Utilities
1
2
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.
3
4
## Capabilities
5
6
### Symbol Constants
7
8
#### $$asyncIterator
9
10
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.
11
12
```javascript { .api }
13
/**
14
* Property name for async iterator method, used for creating new AsyncIterables
15
* @type {Symbol|string}
16
*/
17
export const $$asyncIterator: unique symbol;
18
```
19
20
**Usage Example:**
21
22
```javascript
23
import { $$asyncIterator } from "iterall";
24
25
function Chirper(to) {
26
this.to = to;
27
}
28
29
Chirper.prototype[$$asyncIterator] = function() {
30
return {
31
to: this.to,
32
num: 0,
33
next() {
34
return new Promise((resolve) => {
35
if (this.num >= this.to) {
36
resolve({ value: undefined, done: true });
37
} else {
38
setTimeout(() => {
39
resolve({ value: this.num++, done: false });
40
}, 1000);
41
}
42
});
43
}
44
};
45
};
46
47
const chirper = new Chirper(3);
48
for await (const number of chirper) {
49
console.log(number); // 0 ...wait... 1 ...wait... 2
50
}
51
```
52
53
### Type Checking Functions
54
55
#### isAsyncIterable
56
57
Tests if an object implements the AsyncIterator protocol via `Symbol.asyncIterator` or `"@@asyncIterator"` method.
58
59
```javascript { .api }
60
/**
61
* Tests if object implements AsyncIterator protocol
62
* @param obj - Value to test for AsyncIterable protocol
63
* @returns true if object is AsyncIterable
64
*/
65
function isAsyncIterable(obj: any): obj is AsyncIterable<any>;
66
```
67
68
**Usage Examples:**
69
70
```javascript
71
import { isAsyncIterable } from "iterall";
72
73
// Custom async iterable
74
const asyncGenerator = async function* () {
75
yield 1;
76
yield 2;
77
yield 3;
78
};
79
80
isAsyncIterable(asyncGenerator()); // true - Async generators are async iterable
81
isAsyncIterable([1, 2, 3]); // false - Arrays are not async iterable
82
isAsyncIterable("ABC"); // false - Strings are not async iterable
83
84
// Check before using async iteration
85
if (isAsyncIterable(myStream)) {
86
for await (const item of myStream) {
87
console.log(item);
88
}
89
}
90
```
91
92
### AsyncIterator Creation and Access
93
94
#### getAsyncIterator
95
96
Returns the AsyncIterator object if the provided object implements the AsyncIterator protocol, otherwise returns undefined.
97
98
```javascript { .api }
99
/**
100
* Gets AsyncIterator from an AsyncIterable object
101
* @param asyncIterable - AsyncIterable object to get AsyncIterator from
102
* @returns AsyncIterator instance or undefined
103
*/
104
function getAsyncIterator<TValue>(asyncIterable: AsyncIterable<TValue>): AsyncIterator<TValue>;
105
function getAsyncIterator(asyncIterable: any): void | AsyncIterator<any>;
106
```
107
108
**Usage Example:**
109
110
```javascript
111
import { getAsyncIterator } from "iterall";
112
113
const asyncIterator = getAsyncIterator(myAsyncStream);
114
if (asyncIterator) {
115
const result1 = await asyncIterator.next(); // { value: ..., done: false }
116
const result2 = await asyncIterator.next(); // { value: ..., done: false }
117
const result3 = await asyncIterator.next(); // { value: undefined, done: true }
118
}
119
```
120
121
#### getAsyncIteratorMethod
122
123
Returns the method responsible for producing the AsyncIterator object. Used for performance tuning in rare cases.
124
125
```javascript { .api }
126
/**
127
* Gets the @@asyncIterator method from an AsyncIterable object
128
* @param asyncIterable - AsyncIterable object with @@asyncIterator method
129
* @returns @@asyncIterator method or undefined
130
*/
131
function getAsyncIteratorMethod<TValue>(asyncIterable: AsyncIterable<TValue>): () => AsyncIterator<TValue>;
132
function getAsyncIteratorMethod(asyncIterable: any): void | (() => AsyncIterator<any>);
133
```
134
135
**Usage Example:**
136
137
```javascript
138
import { getAsyncIteratorMethod } from "iterall";
139
140
const method = getAsyncIteratorMethod(myAsyncStream);
141
if (method) {
142
const asyncIterator = method.call(myAsyncStream);
143
const result = await asyncIterator.next();
144
}
145
```
146
147
#### createAsyncIterator
148
149
Creates an AsyncIterator for AsyncIterables, Iterables containing Promises, and Array-like collections. Provides universal AsyncIterator creation with automatic sync-to-async wrapping.
150
151
```javascript { .api }
152
/**
153
* Creates AsyncIterator from various source types
154
* @param source - AsyncIterable, Iterable with Promises, or Array-like object
155
* @returns AsyncIterator instance or undefined
156
*/
157
function createAsyncIterator<TValue>(
158
collection: AsyncIterable<TValue> | Iterable<Promise<TValue> | TValue>
159
): AsyncIterator<TValue>;
160
function createAsyncIterator(collection: { length: number }): AsyncIterator<any>;
161
function createAsyncIterator(collection: any): void | AsyncIterator<any>;
162
```
163
164
**Usage Examples:**
165
166
```javascript
167
import { createAsyncIterator } from "iterall";
168
169
// Works with AsyncIterables
170
const asyncIterator = createAsyncIterator(myAsyncStream);
171
172
// Works with Iterables containing Promises
173
const promiseArray = [
174
Promise.resolve("first"),
175
Promise.resolve("second"),
176
Promise.resolve("third")
177
];
178
const promiseIterator = createAsyncIterator(promiseArray);
179
180
// Works with Array-like objects
181
const arrayLike = { length: 3, 0: "Alpha", 1: "Bravo", 2: "Charlie" };
182
const arrayLikeAsyncIterator = createAsyncIterator(arrayLike);
183
184
if (arrayLikeAsyncIterator) {
185
const result1 = await arrayLikeAsyncIterator.next(); // { value: "Alpha", done: false }
186
const result2 = await arrayLikeAsyncIterator.next(); // { value: "Bravo", done: false }
187
const result3 = await arrayLikeAsyncIterator.next(); // { value: "Charlie", done: false }
188
const result4 = await arrayLikeAsyncIterator.next(); // { value: undefined, done: true }
189
}
190
191
// Mixed sync/async values
192
const mixedIterable = [1, Promise.resolve(2), 3];
193
const mixedIterator = createAsyncIterator(mixedIterable);
194
// Handles both immediate values and promises consistently
195
```
196
197
### Async Iteration Utilities
198
199
#### forAwaitEach
200
201
Asynchronously 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.
202
203
```javascript { .api }
204
/**
205
* Asynchronously iterates over collection, calling callback for each item
206
* @param source - AsyncIterable, Iterable with Promises, or Array-like object
207
* @param callbackFn - Function called for each item (value, index, collection)
208
* @param thisArg - Optional value to use as 'this' in callback
209
* @returns Promise that resolves when iteration completes
210
*/
211
function forAwaitEach<TCollection extends AsyncIterable<any>>(
212
collection: TCollection,
213
callbackFn: (value: ResolvedOf<TCollection>, index: number, collection: TCollection) => any,
214
thisArg?: any
215
): Promise<void>;
216
function forAwaitEach<TCollection extends Iterable<any>>(
217
collection: TCollection,
218
callbackFn: (value: ResolvedOf<TCollection>, index: number, collection: TCollection) => any,
219
thisArg?: any
220
): Promise<void>;
221
function forAwaitEach<TCollection extends { length: number }>(
222
collection: TCollection,
223
callbackFn: (value: any, index: number, collection: TCollection) => any,
224
thisArg?: any
225
): Promise<void>;
226
```
227
228
**Usage Examples:**
229
230
```javascript
231
import { forAwaitEach } from "iterall";
232
233
// Basic async iteration
234
await forAwaitEach(myAsyncStream, async (value, index) => {
235
const processed = await processValue(value);
236
console.log(`Item ${index}:`, processed);
237
});
238
239
// Works with Promise arrays
240
const promiseArray = [
241
fetch("/api/user/1").then(r => r.json()),
242
fetch("/api/user/2").then(r => r.json()),
243
fetch("/api/user/3").then(r => r.json())
244
];
245
246
await forAwaitEach(promiseArray, (user, index) => {
247
console.log(`User ${index}:`, user.name);
248
});
249
250
// Mixed sync/async processing
251
await forAwaitEach([1, 2, 3], async (number) => {
252
if (number % 2 === 0) {
253
const result = await heavyAsyncOperation(number);
254
console.log("Async result:", result);
255
} else {
256
console.log("Sync result:", number * 2);
257
}
258
});
259
260
// Using thisArg
261
const processor = {
262
prefix: "Processed: ",
263
async processItem(value) {
264
return this.prefix + value;
265
}
266
};
267
268
await forAwaitEach([1, 2, 3], async function(value) {
269
const result = await this.processItem(value);
270
console.log(result);
271
}, processor);
272
```
273
274
**Error Handling:**
275
276
```javascript
277
import { forAwaitEach } from "iterall";
278
279
try {
280
await forAwaitEach(myAsyncData, async (item) => {
281
if (item.shouldFail) {
282
throw new Error("Processing failed");
283
}
284
return processItem(item);
285
});
286
} catch (error) {
287
console.error("Iteration failed:", error);
288
}
289
```
290
291
**Performance Notes:**
292
293
- Processes items sequentially, not in parallel
294
- Each callback waits for the previous one to complete
295
- For parallel processing, use `Promise.all()` with regular iteration
296
- Requires `Promise` support (polyfill needed for IE11 and older)
297
298
**Comparison with Native Syntax:**
299
300
```javascript
301
// Native for-await-of (ES2018+)
302
for await (const value of myAsyncIterable) {
303
console.log(await doSomethingAsync(value));
304
}
305
console.log("done");
306
307
// Equivalent using forAwaitEach (works in any environment)
308
await forAwaitEach(myAsyncIterable, async (value) => {
309
console.log(await doSomethingAsync(value));
310
});
311
console.log("done");
312
```