A lightweight Promises/A+ and when() implementation, plus other async goodies.
npx @tessl/cli install tessl/npm-when@3.7.00
# When.js
1
2
## Overview
3
4
When.js is a battle-tested Promises/A+ and when() implementation that provides a comprehensive suite of asynchronous utilities for JavaScript. It offers a powerful combination of small size, high performance, and rich features for managing complex asynchronous flows through promise chaining, error handling, and control flow utilities.
5
6
## Package Information
7
8
- **Name**: when
9
- **Type**: Promise library
10
- **Language**: JavaScript
11
- **Installation**: `npm install when`
12
13
## Core Imports
14
15
```typescript
16
// ESM
17
import when from "when";
18
import { resolve, reject, all, map } from "when";
19
20
// CommonJS
21
const when = require("when");
22
const { resolve, reject, all, map } = when;
23
24
// AMD
25
define(['when'], function(when) {
26
// use when
27
});
28
```
29
30
## Basic Usage
31
32
```typescript
33
// Create and transform promises
34
when(someValue)
35
.then(result => result * 2)
36
.catch(error => console.error('Error:', error));
37
38
// Promise creation
39
const promise = when.resolve("hello world");
40
const rejected = when.reject(new Error("failed"));
41
42
// Array processing
43
when.all([promise1, promise2, promise3])
44
.then(results => console.log('All resolved:', results));
45
```
46
47
## Core Promise API
48
49
### Main when() Function
50
51
```typescript { .api }
52
/**
53
* Get a trusted promise for value x, or transform x with callbacks
54
* @param x - Value or promise to resolve
55
* @param onFulfilled - Success callback
56
* @param onRejected - Error callback
57
* @param onProgress - Progress callback (deprecated)
58
* @returns Promise for the result
59
*/
60
function when<T, U>(
61
x: T | Promise<T>,
62
onFulfilled?: (value: T) => U | Promise<U>,
63
onRejected?: (reason: any) => U | Promise<U>,
64
onProgress?: (update: any) => void
65
): Promise<U>;
66
```
67
68
### Promise Creation
69
70
```typescript { .api }
71
/**
72
* Create a new promise with a resolver function
73
* @param resolver - Function that receives resolve, reject, notify callbacks
74
* @returns New promise
75
*/
76
function promise<T>(
77
resolver: (
78
resolve: (value: T) => void,
79
reject: (reason: any) => void,
80
notify: (progress: any) => void
81
) => void
82
): Promise<T>;
83
84
/**
85
* Create a resolved promise
86
* @param value - Value to resolve with
87
* @returns Promise resolved with value
88
*/
89
function resolve<T>(value: T | Promise<T>): Promise<T>;
90
91
/**
92
* Create a rejected promise
93
* @param reason - Rejection reason
94
* @returns Promise rejected with reason
95
*/
96
function reject<T = never>(reason: any): Promise<T>;
97
```
98
99
### Deferred Objects
100
101
```typescript { .api }
102
interface Deferred<T> {
103
/** The underlying promise */
104
promise: Promise<T>;
105
/** Resolve the promise */
106
resolve: (value: T) => void;
107
/** Reject the promise */
108
reject: (reason: any) => void;
109
/** Notify progress (deprecated) */
110
notify: (progress: any) => void;
111
/** Resolver object with resolve/reject/notify methods */
112
resolver: {
113
resolve: (value: T) => void;
114
reject: (reason: any) => void;
115
notify: (progress: any) => void;
116
};
117
}
118
119
/**
120
* Create a deferred promise/resolver pair
121
* @returns Deferred object with promise and resolver methods
122
*/
123
function defer<T>(): Deferred<T>;
124
```
125
126
## Function Lifting and Execution
127
128
### Function Lifting
129
130
```typescript { .api }
131
// Import from when/function module
132
import { lift, apply, call, compose } from "when/function";
133
134
/**
135
* Lift a function to work with promises as arguments and return promises
136
* @param f - Function to lift
137
* @returns Promise-aware version of the function
138
*/
139
function lift<TArgs extends any[], TResult>(
140
f: (...args: TArgs) => TResult
141
): (...args: { [K in keyof TArgs]: TArgs[K] | Promise<TArgs[K]> }) => Promise<TResult>;
142
143
/**
144
* Apply a function with args array and return a promise for its result
145
* @param f - Function to apply
146
* @param args - Arguments array to pass to function
147
* @returns Promise for function result
148
*/
149
function apply<TArgs extends any[], TResult>(
150
f: (...args: TArgs) => TResult,
151
args: TArgs
152
): Promise<TResult>;
153
154
/**
155
* Call a function and return a promise for its result (alias for when.try)
156
* @param f - Function to call
157
* @param args - Arguments to pass to function
158
* @returns Promise for function result
159
*/
160
function call<TResult>(f: () => TResult): Promise<TResult>;
161
function call<T1, TResult>(f: (arg1: T1) => TResult, arg1: T1): Promise<TResult>;
162
163
/**
164
* Compose functions into a promise-aware pipeline
165
* @param f - First function to receive arguments
166
* @param funcs - Additional functions to compose in sequence
167
* @returns Composed function that returns a promise
168
*/
169
function compose<TArgs extends any[], TResult>(
170
f: (...args: TArgs) => any,
171
...funcs: ((arg: any) => any)[]
172
): (...args: TArgs) => Promise<TResult>;
173
```
174
175
## Array and Collection Operations
176
177
### Promise Arrays
178
179
```typescript { .api }
180
/**
181
* Resolve all promises in an array
182
* @param promises - Array of promises or values
183
* @returns Promise for array of resolved values
184
*/
185
function all<T>(promises: (T | Promise<T>)[]): Promise<T[]>;
186
187
/**
188
* Settle all promises (resolve or reject) and return outcome descriptors
189
* @param promises - Array of promises or values
190
* @returns Promise for array of settlement descriptors
191
*/
192
function settle<T>(promises: (T | Promise<T>)[]): Promise<SettleDescriptor<T>[]>;
193
194
interface SettleDescriptor<T> {
195
state: "fulfilled" | "rejected";
196
value?: T;
197
reason?: any;
198
}
199
200
/**
201
* Join multiple promises (variadic version of all)
202
* @param promises - Promise arguments to join
203
* @returns Promise for array of resolved values
204
*/
205
function join<T extends any[]>(...promises: { [K in keyof T]: T[K] | Promise<T[K]> }): Promise<T>;
206
```
207
208
### Promise Racing
209
210
```typescript { .api }
211
/**
212
* Race promises, resolving with first to settle
213
* @param promises - Array of promises to race
214
* @returns Promise that resolves/rejects with first settlement
215
*/
216
function race<T>(promises: (T | Promise<T>)[]): Promise<T>;
217
218
/**
219
* Resolve with first promise to fulfill (ignores rejections until all reject)
220
* @param promises - Array of promises
221
* @returns Promise for first fulfilled value
222
*/
223
function any<T>(promises: (T | Promise<T>)[]): Promise<T>;
224
225
/**
226
* Resolve with first N promises to fulfill
227
* @param promises - Array of promises
228
* @param count - Number of fulfillments needed
229
* @returns Promise for array of first N fulfilled values
230
*/
231
function some<T>(promises: (T | Promise<T>)[], count: number): Promise<T[]>;
232
```
233
234
### Array Processing
235
236
```typescript { .api }
237
/**
238
* Promise-aware array map function
239
* @param promises - Array of promises or values
240
* @param mapFunc - Mapping function (may return promise)
241
* @returns Promise for array of mapped values
242
*/
243
function map<T, U>(
244
promises: (T | Promise<T>)[],
245
mapFunc: (value: T, index: number) => U | Promise<U>
246
): Promise<U[]>;
247
248
/**
249
* Promise-aware array filter function
250
* @param promises - Array of promises or values
251
* @param predicate - Filter predicate (may return promise)
252
* @returns Promise for array of filtered values
253
*/
254
function filter<T>(
255
promises: (T | Promise<T>)[],
256
predicate: (value: T, index: number) => boolean | Promise<boolean>
257
): Promise<T[]>;
258
259
/**
260
* Promise-aware array reduce function
261
* @param promises - Array of promises or values
262
* @param reducer - Reducer function (may return promise)
263
* @param initialValue - Initial accumulator value
264
* @returns Promise for final reduced value
265
*/
266
function reduce<T, U>(
267
promises: (T | Promise<T>)[],
268
reducer: (accumulator: U, value: T, index: number) => U | Promise<U>,
269
initialValue: U
270
): Promise<U>;
271
272
/**
273
* Promise-aware array reduceRight function
274
* @param promises - Array of promises or values
275
* @param reducer - Reducer function (may return promise)
276
* @param initialValue - Initial accumulator value
277
* @returns Promise for final reduced value
278
*/
279
function reduceRight<T, U>(
280
promises: (T | Promise<T>)[],
281
reducer: (accumulator: U, value: T, index: number) => U | Promise<U>,
282
initialValue: U
283
): Promise<U>;
284
```
285
286
## Promise Instance Methods
287
288
### Core Methods
289
290
```typescript { .api }
291
interface Promise<T> {
292
/**
293
* Standard Promises/A+ then method
294
* @param onFulfilled - Success callback
295
* @param onRejected - Error callback
296
* @param onProgress - Progress callback (deprecated)
297
* @returns New promise for callback result
298
*/
299
then<U>(
300
onFulfilled?: (value: T) => U | Promise<U>,
301
onRejected?: (reason: any) => U | Promise<U>,
302
onProgress?: (progress: any) => void
303
): Promise<U>;
304
305
/**
306
* Catch promise rejections
307
* @param onRejected - Error callback
308
* @returns New promise
309
*/
310
catch<U>(onRejected: (reason: any) => U | Promise<U>): Promise<T | U>;
311
312
/**
313
* Execute callback regardless of outcome
314
* @param onFinally - Cleanup callback
315
* @returns Promise with original value/reason
316
*/
317
finally(onFinally: () => void | Promise<void>): Promise<T>;
318
}
319
```
320
321
### Timing Methods
322
323
```typescript { .api }
324
interface Promise<T> {
325
/**
326
* Delay promise resolution
327
* @param ms - Delay in milliseconds
328
* @returns Promise that resolves after delay with same value
329
*/
330
delay(ms: number): Promise<T>;
331
332
/**
333
* Add timeout to promise
334
* @param ms - Timeout in milliseconds
335
* @param reason - Custom timeout reason
336
* @returns Promise that rejects if timeout exceeded
337
*/
338
timeout(ms: number, reason?: any): Promise<T>;
339
}
340
```
341
342
### Inspection and Utilities
343
344
```typescript { .api }
345
interface PromiseInspection<T> {
346
/** Current state of the promise */
347
state: "pending" | "fulfilled" | "rejected";
348
/** Resolved value (only if fulfilled) */
349
value?: T;
350
/** Rejection reason (only if rejected) */
351
reason?: any;
352
}
353
354
interface Promise<T> {
355
/**
356
* Synchronously inspect promise state
357
* @returns Inspection object with state and value/reason
358
*/
359
inspect(): PromiseInspection<T>;
360
361
/**
362
* Execute side effect without changing promise value
363
* @param onFulfilled - Side effect callback
364
* @returns Promise with original value
365
*/
366
tap(onFulfilled: (value: T) => void | Promise<void>): Promise<T>;
367
368
/**
369
* Spread array result as function arguments
370
* @param onFulfilled - Callback that receives spread arguments
371
* @returns Promise for callback result
372
*/
373
spread<U>(onFulfilled: (...values: T extends any[] ? T : [T]) => U | Promise<U>): Promise<U>;
374
}
375
```
376
377
## Object/Key Operations
378
379
```typescript { .api }
380
// Import from when/keys module
381
import { all as keysAll, map as keysMap, settle as keysSettle } from "when/keys";
382
383
/**
384
* Resolve all properties of an object
385
* @param object - Object with promise or value properties
386
* @returns Promise for object with resolved properties
387
*/
388
function keysAll<T extends Record<string, any>>(
389
object: { [K in keyof T]: T[K] | Promise<T[K]> }
390
): Promise<T>;
391
392
/**
393
* Map over object properties with promise-aware function
394
* @param object - Object to map over
395
* @param mapFunc - Mapping function for values
396
* @returns Promise for object with mapped values
397
*/
398
function keysMap<T, U>(
399
object: Record<string, T | Promise<T>>,
400
mapFunc: (value: T, key: string) => U | Promise<U>
401
): Promise<Record<string, U>>;
402
403
/**
404
* Settle all properties of an object
405
* @param object - Object with promise or value properties
406
* @returns Promise for object with settlement descriptors
407
*/
408
function keysSettle<T extends Record<string, any>>(
409
object: { [K in keyof T]: T[K] | Promise<T[K]> }
410
): Promise<{ [K in keyof T]: SettleDescriptor<T[K]> }>;
411
```
412
413
## Task Flow Control
414
415
### Parallel Execution
416
417
```typescript { .api }
418
/**
419
* Run array of tasks in parallel with same arguments
420
* @param tasks - Array of task functions
421
* @param args - Arguments to pass to all tasks
422
* @returns Promise for array of task results
423
*/
424
function parallel<T extends any[], U>(
425
tasks: ((...args: T) => U | Promise<U>)[],
426
...args: T
427
): Promise<U[]>;
428
```
429
430
### Sequential Execution
431
432
```typescript { .api }
433
/**
434
* Run array of tasks in sequence with same arguments
435
* @param tasks - Array of task functions
436
* @param args - Arguments to pass to all tasks
437
* @returns Promise for array of task results
438
*/
439
function sequence<T extends any[], U>(
440
tasks: ((...args: T) => U | Promise<U>)[],
441
...args: T
442
): Promise<U[]>;
443
```
444
445
### Pipeline Execution
446
447
```typescript { .api }
448
/**
449
* Run tasks in pipeline where each receives result of previous
450
* @param tasks - Array of task functions
451
* @param initialArgs - Arguments for first task
452
* @returns Promise for final task result
453
*/
454
function pipeline<T extends any[], U>(
455
tasks: [(...args: T) => any, ...((arg: any) => any)[]],
456
...initialArgs: T
457
): Promise<U>;
458
```
459
460
## Polling and Monitoring
461
462
```typescript { .api }
463
interface CancelablePromise<T> extends Promise<T> {
464
/** Cancel the polling operation */
465
cancel(): void;
466
}
467
468
/**
469
* Poll a task until condition is met or cancelled
470
* @param task - Task function to poll
471
* @param interval - Polling interval in milliseconds
472
* @param verifier - Optional condition verifier
473
* @returns Cancelable promise for polling result
474
*/
475
function poll<T>(
476
task: () => T | Promise<T>,
477
interval: number,
478
verifier?: (result: T) => boolean | Promise<boolean>
479
): CancelablePromise<T>;
480
```
481
482
## Callback Integration
483
484
### Callback Lifting
485
486
```typescript { .api }
487
// Import from when/callbacks module
488
import { lift, apply, call, promisify } from "when/callbacks";
489
490
/**
491
* Lift callback-style function to promise-returning function
492
* @param callbackFunc - Function expecting callback(err, result)
493
* @returns Promise-returning version of function
494
*/
495
function lift<TArgs extends any[], TResult>(
496
callbackFunc: (...args: [...TArgs, (err: any, result?: TResult) => void]) => void
497
): (...args: TArgs) => Promise<TResult>;
498
499
/**
500
* Apply callback-style function with args array and return promise
501
* @param callbackFunc - Function expecting callback(err, result)
502
* @param args - Arguments array for function
503
* @returns Promise for function result
504
*/
505
function apply<TArgs extends any[], TResult>(
506
callbackFunc: (...args: [...TArgs, (err: any, result?: TResult) => void]) => void,
507
args: TArgs
508
): Promise<TResult>;
509
510
/**
511
* Call callback-style function with individual arguments
512
* @param callbackFunc - Function expecting callback(err, result)
513
* @param args - Arguments for function
514
* @returns Promise for function result
515
*/
516
function call<TArgs extends any[], TResult>(
517
callbackFunc: (...args: [...TArgs, (err: any, result?: TResult) => void]) => void,
518
...args: TArgs
519
): Promise<TResult>;
520
```
521
522
### Node.js Integration
523
524
```typescript { .api }
525
// Import from when/node module
526
import { lift, apply, call, createCallback, bindCallback, liftCallback } from "when/node";
527
528
/**
529
* Lift Node.js-style callback function to promise-returning function
530
* @param nodeFunc - Function expecting Node-style callback(err, result)
531
* @returns Promise-returning version of function
532
*/
533
function lift<TArgs extends any[], TResult>(
534
nodeFunc: (...args: [...TArgs, (err: any, result?: TResult) => void]) => void
535
): (...args: TArgs) => Promise<TResult>;
536
537
/**
538
* Apply Node.js-style function with args array and return promise
539
* @param nodeFunc - Function expecting Node-style callback(err, result)
540
* @param args - Arguments array for function
541
* @returns Promise for function result
542
*/
543
function apply<TArgs extends any[], TResult>(
544
nodeFunc: (...args: [...TArgs, (err: any, result?: TResult) => void]) => void,
545
args: TArgs
546
): Promise<TResult>;
547
548
/**
549
* Call Node.js-style function with individual arguments and return promise
550
* @param nodeFunc - Function expecting Node-style callback(err, result)
551
* @param args - Arguments for function
552
* @returns Promise for function result
553
*/
554
function call<TArgs extends any[], TResult>(
555
nodeFunc: (...args: [...TArgs, (err: any, result?: TResult) => void]) => void,
556
...args: TArgs
557
): Promise<TResult>;
558
559
/**
560
* Create a Node.js-style callback from a resolver
561
* @param resolver - Promise resolver with resolve/reject methods
562
* @returns Node-style callback function
563
*/
564
function createCallback(resolver: {
565
resolve: (value: any) => void;
566
reject: (reason: any) => void;
567
}): (err: any, value?: any) => void;
568
569
/**
570
* Bind a Node.js-style callback to a promise
571
* @param promise - Promise to bind callback to
572
* @param callback - Node-style callback function
573
* @returns Promise with same state as input promise
574
*/
575
function bindCallback<T>(
576
promise: Promise<T>,
577
callback: (err: any, value?: T) => void
578
): Promise<T>;
579
580
/**
581
* Lift a Node.js-style callback to accept promises
582
* @param callback - Node-style callback to lift
583
* @returns Function that accepts a promise and calls callback on resolution
584
*/
585
function liftCallback(
586
callback: (err: any, value?: any) => void
587
): (promise: Promise<any>) => Promise<any>;
588
```
589
590
## Utilities
591
592
### Type Guards
593
594
```typescript { .api }
595
/**
596
* Check if value is thenable (promise-like)
597
* @param x - Value to test
598
* @returns True if value has then method
599
*/
600
function isPromiseLike(x: any): x is Promise<any>;
601
```
602
603
### Error Types
604
605
```typescript { .api }
606
/**
607
* Error thrown when promise times out
608
*/
609
class TimeoutError extends Error {
610
constructor(message?: string);
611
}
612
```
613
614
## Module Exports
615
616
When.js provides multiple ways to access its functionality:
617
618
```typescript
619
// Main module exports
620
import when from "when";
621
import * as callbacks from "when/callbacks";
622
import * as fn from "when/function";
623
import * as keys from "when/keys";
624
import * as node from "when/node";
625
import parallel from "when/parallel";
626
import sequence from "when/sequence";
627
import pipeline from "when/pipeline";
628
import poll from "when/poll";
629
import delay from "when/delay";
630
import timeout from "when/timeout";
631
import guard from "when/guard";
632
import * as generator from "when/generator";
633
634
// ES6 Promise shim
635
import Promise from "when/es6-shim/Promise";
636
```
637
638
## Common Patterns
639
640
### Promise Chaining
641
```typescript
642
when(getData())
643
.then(processData)
644
.then(saveData)
645
.catch(handleError)
646
.finally(cleanup);
647
```
648
649
### Error Propagation
650
```typescript
651
when.resolve(value)
652
.then(step1)
653
.catch(recoverFromStep1Error)
654
.then(step2)
655
.catch(handleFinalError);
656
```
657
658
### Array Processing
659
```typescript
660
const urls = ['url1', 'url2', 'url3'];
661
when.map(urls, fetchUrl)
662
.then(results => when.all(results.map(processResponse)))
663
.then(processedData => console.log('All done:', processedData));
664
```
665
666
### Conditional Processing
667
```typescript
668
when(condition)
669
.then(result => result ? doSomething() : doSomethingElse())
670
.then(handleResult);
671
```
672
673
## Execution Guards
674
675
```typescript { .api }
676
// Import from when/guard module
677
import guard from "when/guard";
678
679
/**
680
* Create guarded version of function that can only execute when condition allows
681
* @param condition - Function that returns promise for condition check
682
* @param f - Function to guard
683
* @returns Guarded version of function
684
*/
685
function guard<TArgs extends any[], TResult>(
686
condition: () => Promise<any>,
687
f: (...args: TArgs) => TResult | Promise<TResult>
688
): (...args: TArgs) => Promise<TResult>;
689
690
/**
691
* Create guard that limits concurrent executions to N
692
* @param count - Maximum number of concurrent executions
693
* @returns Guard condition function
694
*/
695
function guardN(count: number): () => Promise<any>;
696
```
697
698
## Generator Support
699
700
```typescript { .api }
701
// Import from when/generator module
702
import { lift as liftGenerator, call as callGenerator, apply as applyGenerator } from "when/generator";
703
704
/**
705
* Lift a generator function to work with promises and yield
706
* @param generator - Generator function to lift
707
* @returns Promise-aware generator function
708
*/
709
function liftGenerator<TArgs extends any[], TResult>(
710
generator: (...args: TArgs) => Generator<any, TResult, any>
711
): (...args: TArgs) => Promise<TResult>;
712
713
/**
714
* Call generator immediately as promise-aware coroutine
715
* @param generator - Generator function to call
716
* @param args - Arguments to pass to generator
717
* @returns Promise for generator result
718
*/
719
function callGenerator<TArgs extends any[], TResult>(
720
generator: (...args: TArgs) => Generator<any, TResult, any>,
721
...args: TArgs
722
): Promise<TResult>;
723
724
/**
725
* Apply generator with args array as promise-aware coroutine
726
* @param generator - Generator function to apply
727
* @param args - Arguments array for generator
728
* @returns Promise for generator result
729
*/
730
function applyGenerator<TArgs extends any[], TResult>(
731
generator: (...args: TArgs) => Generator<any, TResult, any>,
732
args: TArgs
733
): Promise<TResult>;
734
```
735
736
## Deprecated Modules
737
738
### Standalone Delay (Deprecated)
739
740
```typescript { .api }
741
// Import from when/delay (deprecated - use promise.delay() instead)
742
import delay from "when/delay";
743
744
/**
745
* Create promise that resolves after delay
746
* @deprecated Use when(value).delay(ms) instead
747
* @param ms - Delay in milliseconds
748
* @param value - Value to resolve with after delay
749
* @returns Promise that resolves after delay
750
*/
751
function delay<T>(ms: number, value?: T): Promise<T>;
752
```
753
754
### Standalone Timeout (Deprecated)
755
756
```typescript { .api }
757
// Import from when/timeout (deprecated - use promise.timeout() instead)
758
import timeout from "when/timeout";
759
760
/**
761
* Create promise that times out
762
* @deprecated Use when(promise).timeout(ms) instead
763
* @param ms - Timeout in milliseconds
764
* @param promise - Promise to add timeout to
765
* @returns Promise that rejects if timeout exceeded
766
*/
767
function timeout<T>(ms: number, promise: Promise<T>): Promise<T>;
768
```
769
770
### Unfold Utilities (Deprecated)
771
772
```typescript { .api }
773
// Import from when/unfold (deprecated - use cujojs/most streams instead)
774
import unfold from "when/unfold";
775
import { unfold as unfoldList } from "when/unfold/list";
776
777
/**
778
* Generate promise stream from generator function
779
* @deprecated Use cujojs/most streams instead
780
* @param generator - Function that generates values
781
* @param condition - Condition function to stop generation
782
* @param seed - Initial seed value
783
* @returns Promise for generated sequence
784
*/
785
function unfold<T, U>(
786
generator: (seed: T) => U | Promise<U>,
787
condition: (value: U, seed: T) => boolean | Promise<boolean>,
788
seed: T
789
): Promise<U[]>;
790
```