0
# Promise and Transfer Utilities
1
2
Enhanced Promise implementation with cancellation and timeout support, plus utilities for efficiently transferring objects between workers. These utilities provide additional control over asynchronous operations and performance optimization for worker communication.
3
4
## Capabilities
5
6
### Enhanced Promise Class
7
8
Custom Promise implementation that extends standard Promise functionality with cancellation, timeout, and additional utility methods.
9
10
```javascript { .api }
11
/**
12
* Create a new Promise with enhanced capabilities
13
* @param {function} handler - Promise executor function (resolve, reject) => void
14
* @param {Promise} [parent] - Parent promise for cancellation propagation
15
*/
16
class Promise {
17
constructor(handler, parent)
18
19
/** Standard promise then method with enhanced chaining */
20
then(onSuccess, onFail) -> Promise
21
22
/** Standard promise catch method */
23
catch(onFail) -> Promise
24
25
/** Cancel the promise (rejects with CancellationError) */
26
cancel() -> Promise
27
28
/** Set timeout for promise (rejects with TimeoutError) */
29
timeout(delay) -> Promise
30
31
/** Execute callback on resolve or reject */
32
always(fn) -> Promise
33
34
/** Standard finally method */
35
finally(fn) -> Promise
36
37
/** Promise status properties (readonly) */
38
resolved: boolean
39
rejected: boolean
40
pending: boolean
41
}
42
```
43
44
**Usage Examples:**
45
46
```javascript
47
const workerpool = require('workerpool');
48
const pool = workerpool.pool();
49
50
// Basic promise usage (same as standard Promise)
51
const result = await pool.exec('longTask', [data])
52
.then(result => processResult(result))
53
.catch(error => handleError(error));
54
55
// Promise cancellation
56
const taskPromise = pool.exec('longRunningTask', [data]);
57
58
// Cancel after 5 seconds
59
setTimeout(() => {
60
taskPromise.cancel();
61
}, 5000);
62
63
try {
64
const result = await taskPromise;
65
} catch (error) {
66
if (error instanceof workerpool.Promise.CancellationError) {
67
console.log('Task was cancelled');
68
}
69
}
70
71
// Promise timeout
72
const result = await pool.exec('taskThatMightHang', [data])
73
.timeout(10000) // 10 second timeout
74
.catch(error => {
75
if (error instanceof workerpool.Promise.TimeoutError) {
76
console.log('Task timed out');
77
}
78
throw error;
79
});
80
81
// Always execute cleanup regardless of outcome
82
await pool.exec('taskWithResources', [data])
83
.always(() => {
84
console.log('Cleaning up resources...');
85
cleanup();
86
});
87
```
88
89
### Promise Static Methods
90
91
Static utility methods for working with multiple promises.
92
93
```javascript { .api }
94
/**
95
* Wait for all promises to resolve
96
* @param {Promise[]} promises - Array of promises
97
* @returns {Promise<any[]>} Promise resolving to array of results
98
*/
99
Promise.all(promises) -> Promise<any[]>
100
101
/**
102
* Create a deferred promise with external resolve/reject
103
* @returns {object} Object with promise, resolve, and reject properties
104
*/
105
Promise.defer() -> { promise: Promise, resolve: function, reject: function }
106
```
107
108
**Usage Examples:**
109
110
```javascript
111
// Execute multiple tasks in parallel
112
const tasks = [
113
pool.exec('task1', [data1]),
114
pool.exec('task2', [data2]),
115
pool.exec('task3', [data3])
116
];
117
118
const results = await workerpool.Promise.all(tasks);
119
console.log('All tasks completed:', results);
120
121
// Deferred promise for complex control flow
122
const deferred = workerpool.Promise.defer();
123
124
// Set up async operation with external control
125
setTimeout(() => {
126
if (someCondition) {
127
deferred.resolve('Success!');
128
} else {
129
deferred.reject(new Error('Failed'));
130
}
131
}, 1000);
132
133
const result = await deferred.promise;
134
```
135
136
### Promise Error Classes
137
138
Special error types for promise cancellation and timeout scenarios.
139
140
```javascript { .api }
141
/**
142
* Error thrown when promise is cancelled
143
*/
144
class CancellationError extends Error {
145
constructor(message = 'promise cancelled')
146
}
147
148
/**
149
* Error thrown when promise times out
150
*/
151
class TimeoutError extends Error {
152
constructor(message = 'timeout exceeded')
153
}
154
155
// Access via Promise class
156
Promise.CancellationError = CancellationError
157
Promise.TimeoutError = TimeoutError
158
```
159
160
**Usage Examples:**
161
162
```javascript
163
try {
164
const result = await pool.exec('longTask', [data])
165
.timeout(5000);
166
} catch (error) {
167
if (error instanceof workerpool.Promise.CancellationError) {
168
console.log('Task was cancelled by user');
169
} else if (error instanceof workerpool.Promise.TimeoutError) {
170
console.log('Task timed out after 5 seconds');
171
} else {
172
console.log('Task failed with error:', error.message);
173
}
174
}
175
176
// Handle different error types with specific logic
177
pool.exec('criticalTask', [data])
178
.timeout(30000)
179
.catch(error => {
180
if (error instanceof workerpool.Promise.TimeoutError) {
181
// Retry with longer timeout
182
return pool.exec('criticalTask', [data]).timeout(60000);
183
}
184
throw error; // Re-throw other errors
185
});
186
```
187
188
### Transfer Objects
189
190
Wrapper class for transferable objects that can be efficiently moved between workers without copying data. Only supported in Web Workers and worker_threads environments.
191
192
```javascript { .api }
193
/**
194
* Wrap objects for efficient transfer between workers
195
* @param {any} message - The data to transfer
196
* @param {object[]} transfer - Array of transferable objects
197
*/
198
class Transfer {
199
constructor(message, transfer)
200
message: any // The transferred data
201
transfer: object[] // Array of transferable objects
202
}
203
```
204
205
**Usage Examples:**
206
207
```javascript
208
// In main thread - transfer ArrayBuffer to worker
209
const buffer = new ArrayBuffer(1024 * 1024); // 1MB buffer
210
const uint8Array = new Uint8Array(buffer);
211
212
// Fill with data
213
for (let i = 0; i < uint8Array.length; i++) {
214
uint8Array[i] = i % 256;
215
}
216
217
// Transfer buffer to worker (zero-copy)
218
const result = await pool.exec('processBuffer', [buffer], {
219
transfer: [buffer] // Buffer ownership transferred to worker
220
});
221
222
// buffer is now detached and unusable in main thread
223
console.log(buffer.byteLength); // 0
224
225
// In worker script
226
const workerpool = require('workerpool');
227
228
workerpool.worker({
229
processBuffer: function(buffer) {
230
const uint8Array = new Uint8Array(buffer);
231
232
// Process the buffer
233
for (let i = 0; i < uint8Array.length; i++) {
234
uint8Array[i] = uint8Array[i] * 2;
235
}
236
237
// Return processed buffer back to main thread
238
return new workerpool.Transfer(buffer, [buffer]);
239
},
240
241
createAndTransferBuffer: function(size) {
242
// Create buffer in worker
243
const buffer = new ArrayBuffer(size);
244
const view = new Float32Array(buffer);
245
246
// Fill with computed data
247
for (let i = 0; i < view.length; i++) {
248
view[i] = Math.sin(i / 1000);
249
}
250
251
// Transfer back to main thread
252
return new workerpool.Transfer({
253
buffer: buffer,
254
length: view.length,
255
type: 'Float32Array'
256
}, [buffer]);
257
}
258
});
259
```
260
261
### Advanced Transfer Examples
262
263
```javascript
264
// Transfer multiple objects
265
const canvas = document.createElement('canvas');
266
const ctx = canvas.getContext('2d');
267
const imageData = ctx.createImageData(800, 600);
268
const buffer1 = new ArrayBuffer(1024);
269
const buffer2 = new ArrayBuffer(2048);
270
271
const result = await pool.exec('processMultipleBuffers', [
272
{
273
imageData: imageData,
274
buffer1: buffer1,
275
buffer2: buffer2
276
}
277
], {
278
transfer: [imageData.data.buffer, buffer1, buffer2]
279
});
280
281
// Worker handling multiple transfers
282
workerpool.worker({
283
processMultipleBuffers: function(data) {
284
// Process image data
285
const imageArray = new Uint8ClampedArray(data.imageData.data);
286
// ... process image
287
288
// Process buffers
289
const array1 = new Uint8Array(data.buffer1);
290
const array2 = new Uint8Array(data.buffer2);
291
// ... process arrays
292
293
// Create result with new transferable
294
const resultBuffer = new ArrayBuffer(4096);
295
const resultArray = new Float32Array(resultBuffer);
296
297
// Fill result
298
for (let i = 0; i < resultArray.length; i++) {
299
resultArray[i] = computeResult(i);
300
}
301
302
return new workerpool.Transfer({
303
success: true,
304
resultBuffer: resultBuffer
305
}, [resultBuffer]);
306
}
307
});
308
```
309
310
## Platform Support
311
312
### Transfer Object Compatibility
313
314
Transfer objects are only supported in specific environments:
315
316
- **Web Workers**: Full support for ArrayBuffer, MessagePort, ImageBitmap, etc.
317
- **Worker Threads**: Support for ArrayBuffer and SharedArrayBuffer
318
- **Child Processes**: Transfer objects not supported (data is copied)
319
320
```javascript
321
// Feature detection
322
const supportsTransfer = workerpool.platform === 'browser' ||
323
(workerpool.platform === 'node' && process.versions.node >= '10.5.0');
324
325
if (supportsTransfer) {
326
// Use transfer objects for performance
327
const result = await pool.exec('processLargeBuffer', [buffer], {
328
transfer: [buffer]
329
});
330
} else {
331
// Fall back to regular parameter passing (data copied)
332
const result = await pool.exec('processLargeBuffer', [buffer]);
333
}
334
```
335
336
### Environment-Specific Promise Features
337
338
```javascript
339
// Check if enhanced promises are available
340
const enhancedPromises = typeof workerpool.Promise !== 'undefined';
341
342
if (enhancedPromises) {
343
// Use cancellation and timeout features
344
const task = pool.exec('longTask', [data])
345
.timeout(10000)
346
.catch(error => {
347
if (error instanceof workerpool.Promise.TimeoutError) {
348
console.log('Task timed out');
349
}
350
});
351
} else {
352
// Fall back to standard promise handling
353
const task = pool.exec('longTask', [data]);
354
}
355
```