0
# Utility Functions
1
2
Additional utility functions for promise creation, error handling, async scheduling, and deferred object management.
3
4
## Capabilities
5
6
### Promise Creation Utilities
7
8
#### resolve
9
10
Create a fulfilled promise with the given value.
11
12
```javascript { .api }
13
/**
14
* Create promise resolved with given value
15
* @param value - Value to resolve promise with (can be thenable)
16
* @param label - Optional string for debugging/tooling
17
* @returns Promise resolved with value
18
*/
19
function resolve(value?: any, label?: string): Promise;
20
```
21
22
**Usage Examples:**
23
24
```javascript
25
import { resolve } from "rsvp";
26
27
// Create immediately resolved promise
28
resolve("Hello World")
29
.then(value => console.log(value)); // "Hello World"
30
31
// Resolve with complex object
32
resolve({ user: "John", id: 123 })
33
.then(data => console.log(data.user)); // "John"
34
35
// Resolve with another promise (promise assimilation)
36
const nestedPromise = resolve("nested");
37
resolve(nestedPromise)
38
.then(value => console.log(value)); // "nested"
39
40
// Useful for converting values to promises in chains
41
function processData(input) {
42
if (typeof input === 'string') {
43
return resolve(input.toUpperCase());
44
}
45
return fetchData(input); // returns promise
46
}
47
```
48
49
#### reject
50
51
Create a rejected promise with the given reason.
52
53
```javascript { .api }
54
/**
55
* Create promise rejected with given reason
56
* @param reason - Reason for rejection (typically Error object)
57
* @param label - Optional string for debugging/tooling
58
* @returns Promise rejected with reason
59
*/
60
function reject(reason?: any, label?: string): Promise;
61
```
62
63
**Usage Examples:**
64
65
```javascript
66
import { reject } from "rsvp";
67
68
// Create immediately rejected promise
69
reject(new Error("Something went wrong"))
70
.catch(error => console.error(error.message));
71
72
// Useful for validation flows
73
function validateUser(user) {
74
if (!user.email) {
75
return reject(new Error("Email is required"));
76
}
77
return resolve(user);
78
}
79
80
// Error propagation in promise chains
81
function processRequest(request) {
82
if (!request.isValid) {
83
return reject(new Error("Invalid request"));
84
}
85
return handleRequest(request);
86
}
87
```
88
89
#### defer
90
91
Create a deferred object with manual control over promise resolution.
92
93
```javascript { .api }
94
/**
95
* Create deferred object for manual promise control
96
* @param label - Optional string for debugging/tooling
97
* @returns Object with promise, resolve, and reject properties
98
*/
99
function defer(label?: string): DeferredObject;
100
101
interface DeferredObject {
102
promise: Promise;
103
resolve: Function;
104
reject: Function;
105
}
106
```
107
108
**Usage Examples:**
109
110
```javascript
111
import { defer } from "rsvp";
112
113
// Basic deferred usage
114
const deferred = defer();
115
116
// Resolve later
117
setTimeout(() => {
118
deferred.resolve("Delayed result");
119
}, 1000);
120
121
deferred.promise.then(value => {
122
console.log(value); // "Delayed result" (after 1 second)
123
});
124
125
// Conditional resolution
126
const conditionalDeferred = defer();
127
128
if (someCondition) {
129
conditionalDeferred.resolve("Success");
130
} else {
131
conditionalDeferred.reject(new Error("Failed"));
132
}
133
134
// Useful for converting callback APIs
135
function promisifyCallback(callback) {
136
const deferred = defer();
137
138
callback((error, result) => {
139
if (error) {
140
deferred.reject(error);
141
} else {
142
deferred.resolve(result);
143
}
144
});
145
146
return deferred.promise;
147
}
148
```
149
150
### Error Handling Utilities
151
152
#### rethrow
153
154
Rethrow an error on the next tick for debugging while maintaining promise chain.
155
156
```javascript { .api }
157
/**
158
* Rethrow error on next tick for debugging
159
* @param reason - Error to rethrow
160
* @throws Error both immediately and asynchronously
161
*/
162
function rethrow(reason: any): void;
163
```
164
165
**Usage Examples:**
166
167
```javascript
168
import { rethrow } from "rsvp";
169
170
// Use in promise chains for debugging
171
promise
172
.catch(rethrow) // Throws error to console/debugger
173
.then(() => {
174
// This won't run due to rethrow
175
}, (error) => {
176
// This will handle the error normally
177
console.log("Handled error:", error);
178
});
179
180
// Debugging unhandled promise rejections
181
function createRiskyPromise() {
182
return new Promise((resolve, reject) => {
183
// Simulate error
184
reject(new Error("Something bad happened"));
185
});
186
}
187
188
createRiskyPromise()
189
.catch(rethrow); // Error will appear in console and be re-thrown
190
191
// Note: rethrow both throws immediately and schedules async throw
192
// This allows both immediate handling and console debugging
193
```
194
195
### Async Scheduling Utilities
196
197
#### asap
198
199
Schedule callback to run as soon as possible using the best available method.
200
201
```javascript { .api }
202
/**
203
* Schedule callback to run ASAP using optimal platform method
204
* @param callback - Function to execute
205
* @param arg - Argument to pass to callback
206
*/
207
function asap(callback: Function, arg?: any): void;
208
```
209
210
**Usage Examples:**
211
212
```javascript
213
import { asap } from "rsvp";
214
215
// Schedule immediate callback
216
asap(function(message) {
217
console.log(message);
218
}, "Hello from next tick");
219
220
// Useful for breaking out of synchronous execution
221
function breakSyncChain(value) {
222
asap(function() {
223
processValue(value);
224
});
225
}
226
227
// Custom async pattern
228
function deferredLog(message) {
229
asap(console.log, message);
230
}
231
232
deferredLog("This will log asynchronously");
233
console.log("This logs first");
234
```
235
236
#### async
237
238
Alias for the configured async scheduling function.
239
240
```javascript { .api }
241
/**
242
* Execute callback using configured async scheduler
243
* @param callback - Function to execute
244
* @param arg - Argument to pass to callback
245
*/
246
function async(callback: Function, arg?: any): void;
247
```
248
249
**Usage Examples:**
250
251
```javascript
252
import { async, configure } from "rsvp";
253
254
// Uses the configured async function (same as asap by default)
255
async(function(data) {
256
console.log("Async execution:", data);
257
}, { key: "value" });
258
259
// Can be customized via configuration
260
configure('async', function(callback, arg) {
261
// Custom scheduling logic
262
requestAnimationFrame(() => callback(arg));
263
});
264
265
// Now async() uses requestAnimationFrame
266
async(function() {
267
console.log("Scheduled with requestAnimationFrame");
268
});
269
```
270
271
## Legacy Support
272
273
### cast
274
275
Deprecated alias for `resolve`, maintained for backwards compatibility.
276
277
```javascript { .api }
278
/**
279
* @deprecated Use resolve() instead
280
* Create promise resolved with given value
281
* @param value - Value to resolve promise with
282
* @param label - Optional string for debugging/tooling
283
* @returns Promise resolved with value
284
*/
285
const cast: Function; // Same as resolve
286
```
287
288
**Usage (not recommended for new code):**
289
290
```javascript
291
import { cast } from "rsvp";
292
293
// Deprecated - use resolve() instead
294
cast("value").then(console.log);
295
296
// Preferred
297
import { resolve } from "rsvp";
298
resolve("value").then(console.log);
299
```
300
301
## Platform-Specific Behavior
302
303
### Async Scheduling Methods
304
305
`asap` uses the best available method for each platform:
306
307
- **Node.js**: `process.nextTick` (or `setImmediate` for Node 0.10.x)
308
- **Modern Browsers**: `MutationObserver`
309
- **Web Workers**: `MessageChannel`
310
- **Vert.x**: `vertx.runOnLoop` or `vertx.runOnContext`
311
- **Fallback**: `setTimeout`
312
313
### Browser Compatibility
314
315
- **asap/async**: All modern browsers and IE9+
316
- **defer**: All environments
317
- **resolve/reject**: All environments
318
- **rethrow**: All environments
319
320
## Common Patterns
321
322
### Converting Synchronous Functions
323
324
```javascript
325
import { resolve, reject } from "rsvp";
326
327
function syncToAsync(syncFunction, input) {
328
try {
329
const result = syncFunction(input);
330
return resolve(result);
331
} catch (error) {
332
return reject(error);
333
}
334
}
335
336
// Usage
337
syncToAsync(JSON.parse, '{"valid": "json"}')
338
.then(parsed => console.log(parsed))
339
.catch(error => console.error("Parse failed:", error));
340
```
341
342
### Deferred Event Handling
343
344
```javascript
345
import { defer } from "rsvp";
346
347
function waitForEvent(emitter, eventName, timeout = 5000) {
348
const deferred = defer();
349
350
const cleanup = () => {
351
emitter.removeListener(eventName, onEvent);
352
clearTimeout(timer);
353
};
354
355
const onEvent = (data) => {
356
cleanup();
357
deferred.resolve(data);
358
};
359
360
const timer = setTimeout(() => {
361
cleanup();
362
deferred.reject(new Error(`Timeout waiting for ${eventName}`));
363
}, timeout);
364
365
emitter.on(eventName, onEvent);
366
return deferred.promise;
367
}
368
369
// Usage
370
waitForEvent(eventEmitter, 'data', 3000)
371
.then(data => console.log("Received:", data))
372
.catch(error => console.error("Event timeout:", error));
373
```
374
375
### Error Debugging
376
377
```javascript
378
import { rethrow } from "rsvp";
379
380
// Enhanced rethrow with context
381
function debugRethrow(context) {
382
return function(error) {
383
console.error(`Error in ${context}:`, error);
384
return rethrow(error);
385
};
386
}
387
388
// Usage
389
fetchUserData(userId)
390
.catch(debugRethrow('user data fetch'))
391
.then(processUser)
392
.catch(debugRethrow('user processing'));
393
```