or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-iterator-utilities.mdindex.mditerator-utilities.md
tile.json

async-iterator-utilities.mddocs/

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

```