0
# Callback API
1
2
Convenient callback-based API for processing data arrays with automatic result collection. The callback API provides a simple interface for transforming datasets where you want all results collected and returned via a callback function.
3
4
## Capabilities
5
6
### Transform with Records and Callback
7
8
Process an array of records with automatic result collection via callback.
9
10
```javascript { .api }
11
/**
12
* Transform an array of records with callback
13
* @param records - Array of data to transform
14
* @param handler - Function to transform each record
15
* @param callback - Completion callback receiving results
16
* @returns Transformer stream instance
17
*/
18
function transform<T, U>(
19
records: Array<T>,
20
handler: Handler<T, U>,
21
callback?: Callback
22
): Transformer;
23
24
/**
25
* Transform with options and callback
26
* @param records - Array of data to transform
27
* @param options - Configuration options
28
* @param handler - Function to transform each record
29
* @param callback - Completion callback receiving results
30
* @returns Transformer stream instance
31
*/
32
function transform<T, U>(
33
records: Array<T>,
34
options: Options,
35
handler: Handler<T, U>,
36
callback?: Callback
37
): Transformer;
38
39
/**
40
* Completion callback for result collection
41
* @param err - Error if transformation failed
42
* @param output - Array of transformed results
43
*/
44
type Callback = (err?: null | Error, output?: any[]) => void;
45
```
46
47
**Usage Examples:**
48
49
```javascript
50
import { transform } from "stream-transform";
51
52
// Basic callback transformation
53
transform([
54
["a", "b", "c"],
55
["1", "2", "3"],
56
["x", "y", "z"]
57
], (record) => {
58
return record.join("|");
59
}, (err, results) => {
60
if (err) {
61
console.error("Transformation failed:", err);
62
return;
63
}
64
console.log(results); // ["a|b|c", "1|2|3", "x|y|z"]
65
});
66
67
// Object transformation with callback
68
const users = [
69
{ name: " Alice ", email: "ALICE@EXAMPLE.COM", age: "25" },
70
{ name: " Bob ", email: "BOB@EXAMPLE.COM", age: "30" }
71
];
72
73
transform(users, (user) => {
74
return {
75
name: user.name.trim(),
76
email: user.email.toLowerCase(),
77
age: parseInt(user.age)
78
};
79
}, (err, cleanUsers) => {
80
if (err) throw err;
81
console.log("Cleaned users:", cleanUsers);
82
});
83
```
84
85
### Transform with Options and Callback
86
87
Enhanced callback API with configuration options for parallel processing and custom parameters.
88
89
```javascript { .api }
90
/**
91
* Transform with options and callback
92
* @param records - Array of data to transform
93
* @param options - Configuration for transformation
94
* @param handler - Function to transform each record
95
* @param callback - Completion callback receiving results
96
* @returns Transformer stream instance
97
*/
98
function transform<T, U>(
99
records: Array<T>,
100
options: Options,
101
handler: Handler<T, U>,
102
callback?: Callback
103
): Transformer;
104
```
105
106
**Usage Examples:**
107
108
```javascript
109
import { transform } from "stream-transform";
110
111
// Parallel processing with callback
112
const largeDataset = Array.from({ length: 10000 }, (_, i) => ({ id: i, value: Math.random() }));
113
114
transform(largeDataset, {
115
parallel: 50 // Process 50 records concurrently
116
}, async (record) => {
117
// Simulate async processing
118
await new Promise(resolve => setTimeout(resolve, 10));
119
return {
120
...record,
121
processed: true,
122
timestamp: Date.now()
123
};
124
}, (err, results) => {
125
if (err) throw err;
126
console.log(`Processed ${results.length} records in parallel`);
127
});
128
129
// Custom parameters with callback
130
const config = {
131
apiEndpoint: "https://api.example.com",
132
timeout: 5000
133
};
134
135
transform([1, 2, 3, 4, 5], {
136
parallel: 3,
137
params: config
138
}, async (id, params) => {
139
const response = await fetch(`${params.apiEndpoint}/items/${id}`, {
140
timeout: params.timeout
141
});
142
return await response.json();
143
}, (err, apiResults) => {
144
if (err) {
145
console.error("API transformation failed:", err);
146
return;
147
}
148
console.log("API results:", apiResults);
149
});
150
```
151
152
### Auto-consumption Mode
153
154
Callback API automatically enables consumption mode, collecting all results without requiring explicit stream handling.
155
156
```javascript { .api }
157
// Auto-consumption is automatically enabled when callback is provided
158
// No need to manually read from the stream - results are collected automatically
159
```
160
161
**Usage Examples:**
162
163
```javascript
164
import { transform } from "stream-transform";
165
166
// Automatic result collection - no stream handling needed
167
transform(["apple", "banana", "cherry"], (fruit) => {
168
return fruit.toUpperCase();
169
}, (err, results) => {
170
// Results are automatically collected
171
console.log(results); // ["APPLE", "BANANA", "CHERRY"]
172
});
173
174
// Even with complex async operations
175
const urls = [
176
"https://api.example.com/users/1",
177
"https://api.example.com/users/2",
178
"https://api.example.com/users/3"
179
];
180
181
transform(urls, {
182
parallel: 2
183
}, async (url) => {
184
const response = await fetch(url);
185
return await response.json();
186
}, (err, users) => {
187
if (err) {
188
console.error("Failed to fetch users:", err);
189
return;
190
}
191
// All users are automatically collected
192
console.log(`Fetched ${users.length} users`);
193
});
194
```
195
196
### Handler Function Patterns
197
198
Callback API supports all handler execution patterns with automatic result collection.
199
200
```javascript { .api }
201
/**
202
* Synchronous handler for callback API
203
*/
204
type SyncHandler<T, U> = (record: T, params?: any) => U;
205
206
/**
207
* Asynchronous handler for callback API
208
*/
209
type AsyncHandler<T, U> = (record: T, callback: HandlerCallback<U>, params?: any) => void;
210
211
/**
212
* Promise-based handler for callback API
213
*/
214
type PromiseHandler<T, U> = (record: T, params?: any) => Promise<U>;
215
```
216
217
**Usage Examples:**
218
219
```javascript
220
import { transform } from "stream-transform";
221
222
// Synchronous handler with callback
223
transform([1, 2, 3, 4, 5], (num) => {
224
return num * num;
225
}, (err, squares) => {
226
console.log(squares); // [1, 4, 9, 16, 25]
227
});
228
229
// Asynchronous handler with callback
230
transform(["file1.txt", "file2.txt"], (filename, callback) => {
231
fs.readFile(filename, 'utf8', (err, content) => {
232
if (err) return callback(err);
233
callback(null, { filename, content, size: content.length });
234
});
235
}, (err, fileData) => {
236
if (err) throw err;
237
console.log("Files read:", fileData);
238
});
239
240
// Promise-based handler with callback
241
transform(["user1", "user2", "user3"], async (username) => {
242
const user = await database.findUser(username);
243
return {
244
username,
245
profile: user,
246
lastSeen: user.lastLoginAt
247
};
248
}, (err, userProfiles) => {
249
if (err) throw err;
250
console.log("User profiles loaded:", userProfiles);
251
});
252
```
253
254
### Error Handling
255
256
Comprehensive error handling with callback-based error reporting.
257
258
```javascript { .api }
259
/**
260
* Error handling in callback API
261
* @param err - Error object if transformation failed, null if successful
262
* @param results - Transformed results if successful, undefined if error
263
*/
264
type Callback = (err?: null | Error, results?: any[]) => void;
265
```
266
267
**Usage Examples:**
268
269
```javascript
270
import { transform } from "stream-transform";
271
272
// Basic error handling
273
transform([1, 2, "invalid", 4], (value) => {
274
if (typeof value !== "number") {
275
throw new Error(`Invalid input: expected number, got ${typeof value}`);
276
}
277
return value * 2;
278
}, (err, results) => {
279
if (err) {
280
console.error("Transformation failed:", err.message);
281
// results will be undefined
282
return;
283
}
284
console.log("Results:", results);
285
});
286
287
// Async error handling
288
transform(["valid", "also-valid", ""], (input, callback) => {
289
if (!input || input.trim() === "") {
290
return callback(new Error("Empty input not allowed"));
291
}
292
293
// Simulate async processing
294
setTimeout(() => {
295
callback(null, input.toUpperCase());
296
}, 10);
297
}, (err, results) => {
298
if (err) {
299
console.error("Processing error:", err.message);
300
return;
301
}
302
console.log("Processed:", results);
303
});
304
305
// Promise rejection handling
306
transform([1, 2, 3], async (num) => {
307
if (num === 2) {
308
throw new Error("Number 2 is not allowed");
309
}
310
return num * 10;
311
}, (err, results) => {
312
if (err) {
313
console.error("Promise rejected:", err.message);
314
return;
315
}
316
console.log("Results:", results);
317
});
318
```
319
320
### Performance Considerations
321
322
The callback API is optimized for convenience but has performance characteristics to consider.
323
324
```javascript { .api }
325
// Memory usage: All results are held in memory until completion
326
// Best for: Small to medium datasets (< 100,000 records)
327
// Consider stream API for: Large datasets or memory-constrained environments
328
```
329
330
**Usage Examples:**
331
332
```javascript
333
import { transform } from "stream-transform";
334
335
// Good: Small dataset with callback
336
const smallDataset = Array.from({ length: 1000 }, (_, i) => i);
337
transform(smallDataset, (num) => num * 2, (err, results) => {
338
// Memory usage is acceptable
339
console.log(`Processed ${results.length} items`);
340
});
341
342
// Consider alternatives: Large dataset
343
const largeDataset = Array.from({ length: 1000000 }, (_, i) => i);
344
345
// Option 1: Use stream API for large datasets
346
const streamTransform = transform((num) => num * 2);
347
// Process with streams to avoid memory buildup
348
349
// Option 2: If callback needed, consider chunking
350
const chunkSize = 10000;
351
async function processInChunks(data, handler) {
352
const results = [];
353
for (let i = 0; i < data.length; i += chunkSize) {
354
const chunk = data.slice(i, i + chunkSize);
355
const chunkResults = await new Promise((resolve, reject) => {
356
transform(chunk, handler, (err, res) => {
357
if (err) reject(err);
358
else resolve(res);
359
});
360
});
361
results.push(...chunkResults);
362
}
363
return results;
364
}
365
```