0
# Promise Utilities
1
2
Advanced promise helpers including timeout handling, polling mechanisms, and deferred promise implementation with state tracking. These utilities provide sophisticated asynchronous programming capabilities for Web3 applications.
3
4
## Capabilities
5
6
### Promise Detection
7
8
```typescript { .api }
9
/**
10
* Checks if object is a Promise
11
* @param object - Object to check
12
* @returns true if object is a Promise
13
*/
14
function isPromise(object: unknown): boolean;
15
```
16
17
### Timeout Utilities
18
19
#### Wait with Timeout
20
21
```typescript { .api }
22
/**
23
* Waits for promise with timeout (overloaded function)
24
* @param awaitable - Promise or async function to wait for
25
* @param timeout - Timeout in milliseconds
26
* @param error - Optional error to throw on timeout
27
* @returns Promise that resolves with result or undefined on timeout
28
*/
29
function waitWithTimeout<T>(
30
awaitable: Promise<T> | AsyncFunction<T>,
31
timeout: number,
32
error?: Error
33
): Promise<T | undefined>;
34
```
35
36
#### Timeout Rejection
37
38
```typescript { .api }
39
/**
40
* Creates timeout promise that rejects
41
* @param timeout - Timeout in milliseconds
42
* @param error - Error to reject with
43
* @returns Tuple of timer and rejection promise
44
*/
45
function rejectIfTimeout(timeout: number, error: Error): [Timer, Promise<never>];
46
```
47
48
### Polling Utilities
49
50
#### Polling with Interval ID
51
52
```typescript { .api }
53
/**
54
* Polls function until result is defined, returns interval ID
55
* @param func - Async function to poll
56
* @param interval - Polling interval in milliseconds
57
* @returns Tuple of promise and timer for cleanup
58
*/
59
function pollTillDefinedAndReturnIntervalId<T>(
60
func: AsyncFunction<T>,
61
interval: number
62
): [Promise<Exclude<T, undefined>>, Timer];
63
```
64
65
#### Simple Polling (Deprecated)
66
67
```typescript { .api }
68
/**
69
* Polls function until result is defined
70
* @deprecated Use pollTillDefinedAndReturnIntervalId instead
71
* @param func - Async function to poll
72
* @param interval - Polling interval in milliseconds
73
* @returns Promise that resolves when result is defined
74
*/
75
function pollTillDefined<T>(
76
func: AsyncFunction<T>,
77
interval: number
78
): Promise<Exclude<T, undefined>>;
79
```
80
81
#### Conditional Rejection
82
83
```typescript { .api }
84
/**
85
* Rejects if condition met at intervals
86
* @param cond - Async condition function
87
* @param interval - Check interval in milliseconds
88
* @returns Tuple of timer and rejection promise
89
*/
90
function rejectIfConditionAtInterval<T>(
91
cond: AsyncFunction<T | undefined>,
92
interval: number
93
): [Timer, Promise<never>];
94
```
95
96
### Deferred Promise
97
98
Advanced promise implementation with manual control and state tracking.
99
100
```typescript { .api }
101
/**
102
* Deferred promise with state tracking and timeout support
103
* Implements Promise interface and additional Web3DeferredPromiseInterface
104
*/
105
class Web3DeferredPromise<T> implements Promise<T>, Web3DeferredPromiseInterface<T> {
106
/**
107
* Promise string tag for debugging
108
*/
109
readonly [Symbol.toStringTag]: 'Promise';
110
111
/**
112
* Current state of the promise
113
*/
114
readonly state: 'pending' | 'fulfilled' | 'rejected';
115
116
/**
117
* Creates a new deferred promise
118
* @param options - Configuration options
119
* @param options.timeout - Timeout in milliseconds
120
* @param options.eagerStart - Whether to start timer immediately
121
* @param options.timeoutMessage - Custom timeout error message
122
*/
123
constructor(options?: {
124
timeout?: number;
125
eagerStart?: boolean;
126
timeoutMessage?: string;
127
});
128
129
/**
130
* Promise then method
131
* @param onfulfilled - Success callback
132
* @param onrejected - Error callback
133
* @returns New promise
134
*/
135
then<TResult1 = T, TResult2 = never>(
136
onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
137
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
138
): Promise<TResult1 | TResult2>;
139
140
/**
141
* Promise catch method
142
* @param onrejected - Error callback
143
* @returns New promise
144
*/
145
catch<TResult = never>(
146
onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null
147
): Promise<T | TResult>;
148
149
/**
150
* Promise finally method
151
* @param onfinally - Finally callback
152
* @returns New promise
153
*/
154
finally(onfinally?: (() => void) | null): Promise<T>;
155
156
/**
157
* Manually resolve the promise
158
* @param value - Value or promise to resolve with
159
*/
160
resolve(value: T | PromiseLike<T>): void;
161
162
/**
163
* Manually reject the promise
164
* @param reason - Rejection reason
165
*/
166
reject(reason?: unknown): void;
167
168
/**
169
* Start the timeout timer
170
*/
171
startTimer(): void;
172
}
173
```
174
175
## Usage Examples
176
177
### Basic Promise Utilities
178
179
```typescript
180
import {
181
isPromise, waitWithTimeout, pollTillDefinedAndReturnIntervalId
182
} from "web3-utils";
183
184
// Check if object is promise
185
const maybePromise = fetch('/api/data');
186
if (isPromise(maybePromise)) {
187
const result = await maybePromise;
188
}
189
190
// Wait with timeout
191
try {
192
const result = await waitWithTimeout(
193
fetch('/api/slow-endpoint'),
194
5000, // 5 second timeout
195
new Error('Request timed out')
196
);
197
198
if (result === undefined) {
199
console.log('Operation timed out');
200
} else {
201
console.log('Got result:', result);
202
}
203
} catch (error) {
204
console.error('Error or timeout:', error);
205
}
206
```
207
208
### Polling Examples
209
210
```typescript
211
import { pollTillDefinedAndReturnIntervalId } from "web3-utils";
212
213
// Poll for transaction receipt
214
async function waitForTransactionReceipt(txHash: string) {
215
const [receiptPromise, intervalId] = pollTillDefinedAndReturnIntervalId(
216
async () => {
217
try {
218
const receipt = await web3.eth.getTransactionReceipt(txHash);
219
return receipt; // Returns undefined if not mined yet
220
} catch (error) {
221
return undefined; // Continue polling on error
222
}
223
},
224
1000 // Poll every second
225
);
226
227
try {
228
const receipt = await receiptPromise;
229
console.log('Transaction mined:', receipt);
230
return receipt;
231
} finally {
232
clearInterval(intervalId); // Clean up interval
233
}
234
}
235
236
// Poll for account balance changes
237
async function watchBalance(address: string, expectedAmount: string) {
238
const [balancePromise, intervalId] = pollTillDefinedAndReturnIntervalId(
239
async () => {
240
const balance = await web3.eth.getBalance(address);
241
return balance >= expectedAmount ? balance : undefined;
242
},
243
2000 // Poll every 2 seconds
244
);
245
246
return balancePromise.finally(() => clearInterval(intervalId));
247
}
248
```
249
250
### Deferred Promise Examples
251
252
```typescript
253
import { Web3DeferredPromise } from "web3-utils";
254
255
// Basic deferred promise
256
const deferred = new Web3DeferredPromise<string>();
257
258
// Check state
259
console.log(deferred.state); // "pending"
260
261
// Resolve manually
262
setTimeout(() => {
263
deferred.resolve("Hello World");
264
}, 1000);
265
266
const result = await deferred;
267
console.log(result); // "Hello World"
268
console.log(deferred.state); // "fulfilled"
269
270
// Deferred promise with timeout
271
const deferredWithTimeout = new Web3DeferredPromise<number>({
272
timeout: 5000,
273
eagerStart: true,
274
timeoutMessage: "Operation timed out after 5 seconds"
275
});
276
277
// Will automatically reject after 5 seconds if not resolved
278
try {
279
// Simulate slow operation
280
setTimeout(() => {
281
deferredWithTimeout.resolve(42);
282
}, 3000);
283
284
const result = await deferredWithTimeout;
285
console.log('Result:', result); // 42
286
} catch (error) {
287
console.error('Timeout error:', error);
288
}
289
```
290
291
### Advanced Usage Patterns
292
293
```typescript
294
import {
295
Web3DeferredPromise, rejectIfTimeout, rejectIfConditionAtInterval
296
} from "web3-utils";
297
298
// Custom timeout with cleanup
299
async function fetchWithCustomTimeout<T>(
300
operation: Promise<T>,
301
timeoutMs: number
302
): Promise<T> {
303
const [timeoutTimer, timeoutPromise] = rejectIfTimeout(
304
timeoutMs,
305
new Error(`Operation timed out after ${timeoutMs}ms`)
306
);
307
308
try {
309
return await Promise.race([operation, timeoutPromise]);
310
} finally {
311
clearTimeout(timeoutTimer);
312
}
313
}
314
315
// Conditional timeout based on external condition
316
async function fetchWithConditionalTimeout<T>(
317
operation: Promise<T>,
318
shouldCancel: () => Promise<boolean>
319
): Promise<T> {
320
const [conditionTimer, conditionPromise] = rejectIfConditionAtInterval(
321
shouldCancel,
322
1000 // Check every second
323
);
324
325
try {
326
return await Promise.race([operation, conditionPromise]);
327
} finally {
328
clearInterval(conditionTimer);
329
}
330
}
331
332
// Usage
333
let cancelled = false;
334
const result = await fetchWithConditionalTimeout(
335
longRunningOperation(),
336
async () => cancelled
337
);
338
339
// Cancel after 10 seconds
340
setTimeout(() => { cancelled = true; }, 10000);
341
```
342
343
## Types
344
345
```typescript { .api }
346
// Type definitions for promise utilities
347
type AsyncFunction<T, K = unknown> = (...args: K[]) => Promise<T>;
348
type Timer = ReturnType<typeof setInterval>;
349
type Timeout = ReturnType<typeof setTimeout>;
350
351
interface Web3DeferredPromiseInterface<T> {
352
readonly state: 'pending' | 'fulfilled' | 'rejected';
353
resolve(value: T | PromiseLike<T>): void;
354
reject(reason?: unknown): void;
355
startTimer(): void;
356
}
357
```