@flex-development/when 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/README.md +657 -69
- package/dist/index.d.mts +407 -23
- package/dist/lib/index.mjs +4 -1
- package/dist/lib/is-catchable.mjs +24 -0
- package/dist/lib/is-finalizable.mjs +24 -0
- package/dist/lib/is-promise-like.mjs +24 -0
- package/dist/lib/is-promise.mjs +12 -6
- package/dist/lib/is-thenable.mjs +30 -8
- package/dist/lib/when.mjs +76 -12
- package/dist/testing/index.d.mts +149 -0
- package/dist/testing/index.mjs +5 -0
- package/dist/testing/lib/create-thenable.mjs +350 -0
- package/dist/testing/lib/index.mjs +5 -0
- package/package.json +15 -7
package/README.md
CHANGED
|
@@ -28,15 +28,38 @@ like `.then`, but for synchronous values *and* thenables.
|
|
|
28
28
|
- [Handle failures](#handle-failures)
|
|
29
29
|
- [Bind `this` context](#bind-this-context)
|
|
30
30
|
- [Use an options object](#use-an-options-object)
|
|
31
|
+
- [Integrate with `@typescript-eslint`](#integrate-with-typescript-eslint)
|
|
31
32
|
- [API](#api)
|
|
32
|
-
- [`
|
|
33
|
+
- [`isCatchable<T>(value)`][iscatchable]
|
|
34
|
+
- [`isFinalizable<T>(value)`][isfinalizable]
|
|
35
|
+
- [`isPromise<T>(value[, finalizable])`][ispromise]
|
|
36
|
+
- [`isPromiseLike<T>(value)`][ispromiselike]
|
|
33
37
|
- [`isThenable<T>(value)`][isthenable]
|
|
34
|
-
|
|
38
|
+
<!--lint disable-->
|
|
39
|
+
- [`when<T[, Next][, Failure][, Args][, Error][, This][, Result]>(value, chain[, fail][, context][, ...args])`][when]
|
|
40
|
+
<!--lint enable-->
|
|
41
|
+
- [Testing](#testing)
|
|
42
|
+
- [`createThenable<T[, Reason][, Result]>(executor[, options])`][createthenable]
|
|
35
43
|
- [Types](#types)
|
|
36
44
|
- [`Awaitable<T>`][awaitable]
|
|
45
|
+
- [`Catch<[T][, Reason]>`][catch]
|
|
46
|
+
- [`Catchable<[T]>`][catchable]
|
|
37
47
|
- [`Chain<[T][, Next][, Args][, This]>`][chain]
|
|
38
|
-
- [`
|
|
48
|
+
- [`CreateThenableOptions`][createthenableoptions]
|
|
49
|
+
- [`Executor<[T][, Reason]>`][executor]
|
|
50
|
+
- [`Fail<[Next][, Reason][, This]>`][fail]
|
|
51
|
+
- [`Finalizable<[T]>`][finalizable]
|
|
52
|
+
- [`Finally<[T]>`][finally]
|
|
53
|
+
- [`Finish<[This]>`][finish]
|
|
54
|
+
- [`OnFinally`][onfinally]
|
|
55
|
+
- [`OnFulfilled<T[, Next]>`][onfulfilled]
|
|
56
|
+
- [`OnRejected<Next[, Reason]>`][onrejected]
|
|
39
57
|
- [`Options<[T][, Next][, Failure][, Args][, Error][, This]>`][options]
|
|
58
|
+
- [`PromiseLike<T>`][promiselike]
|
|
59
|
+
- [`Reject<[Reason]>`][reject]
|
|
60
|
+
- [`Resolve<[T]>`][resolve]
|
|
61
|
+
- [`Then<[T][, Reason]>`][then]
|
|
62
|
+
- [`Thenable<[T]>`][thenable]
|
|
40
63
|
- [Glossary](#glossary)
|
|
41
64
|
- [Project](#project)
|
|
42
65
|
- [Version](#version)
|
|
@@ -46,7 +69,7 @@ like `.then`, but for synchronous values *and* thenables.
|
|
|
46
69
|
## What is this?
|
|
47
70
|
|
|
48
71
|
`when` is a tiny primitive for chaining callbacks
|
|
49
|
-
onto [awaitables][awaitable] (synchronous or [*thenable*][thenable] values).
|
|
72
|
+
onto [awaitables][awaitable] (synchronous or [*thenable*][thenable-term] values).
|
|
50
73
|
|
|
51
74
|
For thenable values, `then` is used to invoke the callback after resolution. Otherwise, the callback fires immediately.
|
|
52
75
|
This makes it easy to write one code path that supports both synchronous values and promises.
|
|
@@ -55,7 +78,7 @@ This makes it easy to write one code path that supports both synchronous values
|
|
|
55
78
|
|
|
56
79
|
`when` is especially useful in libraries implementing awaitable APIs.
|
|
57
80
|
|
|
58
|
-
It provides [`Promise.then`][promise-then] semantics without forcing [`Promise.resolve`][promise-resolve],
|
|
81
|
+
It provides [`Promise.prototype.then`][promise-then] semantics without forcing [`Promise.resolve`][promise-resolve],
|
|
59
82
|
preserving synchronous execution whenever possible.
|
|
60
83
|
|
|
61
84
|
Typical use cases include plugin systems, hook pipelines, module resolvers, data loaders, and file system adapters where
|
|
@@ -79,10 +102,9 @@ when(value, fn) // only a promise if `value` is a thenable, or `fn` returns one
|
|
|
79
102
|
### Design guarantees
|
|
80
103
|
|
|
81
104
|
- Synchronous values remain synchronous
|
|
82
|
-
- [*Thenable*s][thenable] are chained without wrapping in [`Promise.resolve`][promise-resolve]
|
|
105
|
+
- [*Thenable*s][thenable-term] are chained directly without wrapping in [`Promise.resolve`][promise-resolve]
|
|
83
106
|
- No additional microtasks are scheduled for non-thenables
|
|
84
107
|
- Failures propagate unless a `fail` handler is provided
|
|
85
|
-
- Returned thenables are preserved without additional wrapping
|
|
86
108
|
|
|
87
109
|
## Install
|
|
88
110
|
|
|
@@ -120,52 +142,52 @@ In browsers with [`esm.sh`][esmsh]:
|
|
|
120
142
|
### Chain a synchronous value
|
|
121
143
|
|
|
122
144
|
```ts
|
|
123
|
-
import { isThenable, when
|
|
145
|
+
import { isThenable, when } from '@flex-development/when'
|
|
124
146
|
import { ok } from 'devlop'
|
|
125
147
|
|
|
126
148
|
/**
|
|
127
149
|
* The result.
|
|
128
150
|
*
|
|
129
|
-
* @const {
|
|
151
|
+
* @const {number} result
|
|
130
152
|
*/
|
|
131
|
-
const result:
|
|
153
|
+
const result: number = when(0, n => n + 1)
|
|
132
154
|
|
|
133
155
|
ok(!isThenable(result), 'expected `result` to not be thenable')
|
|
134
156
|
console.dir(result) // 1
|
|
135
157
|
```
|
|
136
158
|
|
|
137
|
-
### Chain a [*thenable*][thenable]
|
|
159
|
+
### Chain a [*thenable*][thenable-term]
|
|
138
160
|
|
|
139
161
|
```ts
|
|
140
|
-
import {
|
|
162
|
+
import { isPromise, when } from '@flex-development/when'
|
|
141
163
|
import { ok } from 'devlop'
|
|
142
164
|
|
|
143
165
|
/**
|
|
144
166
|
* The result.
|
|
145
167
|
*
|
|
146
|
-
* @const {
|
|
168
|
+
* @const {Promise<number>} result
|
|
147
169
|
*/
|
|
148
|
-
const result:
|
|
170
|
+
const result: Promise<number> = when(Promise.resolve(2), n => n + 1)
|
|
149
171
|
|
|
150
|
-
ok(
|
|
172
|
+
ok(isPromise(result), 'expected `result` to be a promise')
|
|
151
173
|
console.dir(await result) // 3
|
|
152
174
|
```
|
|
153
175
|
|
|
154
176
|
### Pass arguments to the chain callback
|
|
155
177
|
|
|
156
|
-
When arguments are provided, they are passed to the `chain` callback first, followed by the resolved value.
|
|
178
|
+
When arguments are provided, they are passed to the [`chain`][chain] callback first, followed by the resolved value.
|
|
157
179
|
|
|
158
|
-
When the `value` passed to `when` is not [*thenable*][thenable], the resolved value is the same `value`.
|
|
180
|
+
When the `value` passed to `when` is not a [*thenable*][thenable-term], the resolved value is the same `value`.
|
|
159
181
|
|
|
160
182
|
```ts
|
|
161
|
-
import when
|
|
183
|
+
import when from '@flex-development/when'
|
|
162
184
|
|
|
163
185
|
/**
|
|
164
186
|
* The result.
|
|
165
187
|
*
|
|
166
|
-
* @const {
|
|
188
|
+
* @const {number} result
|
|
167
189
|
*/
|
|
168
|
-
const result:
|
|
190
|
+
const result: number = when(
|
|
169
191
|
1, // last argument passed to `Math.min`
|
|
170
192
|
Math.min, // `chain`
|
|
171
193
|
null, // `fail`
|
|
@@ -180,11 +202,11 @@ console.dir(result) // 1
|
|
|
180
202
|
|
|
181
203
|
### Handle failures
|
|
182
204
|
|
|
183
|
-
For [*thenable*s][thenable], the `fail` callback is passed to `then` as the `onrejected` parameter,
|
|
184
|
-
and if implemented, to `catch` as well to prevent unhandled rejections.
|
|
205
|
+
For [*thenable*s][thenable-term], the [`fail`][fail] callback is passed to [`then`][then] as the `onrejected` parameter,
|
|
206
|
+
and if implemented, to [`catch`][catch] as well to prevent unhandled rejections.
|
|
185
207
|
|
|
186
208
|
```ts
|
|
187
|
-
import when
|
|
209
|
+
import when from '@flex-development/when'
|
|
188
210
|
|
|
189
211
|
/**
|
|
190
212
|
* The thenable value.
|
|
@@ -198,9 +220,9 @@ const value: PromiseLike<never> = new Promise((resolve, reject) => {
|
|
|
198
220
|
/**
|
|
199
221
|
* The result.
|
|
200
222
|
*
|
|
201
|
-
* @const {
|
|
223
|
+
* @const {Promise<boolean>} result
|
|
202
224
|
*/
|
|
203
|
-
const result:
|
|
225
|
+
const result: Promise<boolean> = when(value, chain, fail)
|
|
204
226
|
|
|
205
227
|
console.dir(await result) // false
|
|
206
228
|
|
|
@@ -230,7 +252,7 @@ function fail(this: void, e: Error): false {
|
|
|
230
252
|
### Bind `this` context
|
|
231
253
|
|
|
232
254
|
```ts
|
|
233
|
-
import when
|
|
255
|
+
import when from '@flex-development/when'
|
|
234
256
|
|
|
235
257
|
/**
|
|
236
258
|
* The `this` context.
|
|
@@ -240,9 +262,9 @@ type Context = { prefix: string }
|
|
|
240
262
|
/**
|
|
241
263
|
* The result.
|
|
242
264
|
*
|
|
243
|
-
* @const {
|
|
265
|
+
* @const {string} result
|
|
244
266
|
*/
|
|
245
|
-
const result:
|
|
267
|
+
const result: string = when(13, id, null, { prefix: 'id:' })
|
|
246
268
|
|
|
247
269
|
console.log(result) // 'id:13'
|
|
248
270
|
|
|
@@ -262,8 +284,6 @@ function id(this: Context, num: number | string): string {
|
|
|
262
284
|
### Use an options object
|
|
263
285
|
|
|
264
286
|
```ts
|
|
265
|
-
import when, { type Awaitable } from '@flex-development/when'
|
|
266
|
-
|
|
267
287
|
/**
|
|
268
288
|
* The `this` context.
|
|
269
289
|
*/
|
|
@@ -279,9 +299,9 @@ const value: Promise<number> = new Promise(resolve => resolve(3))
|
|
|
279
299
|
/**
|
|
280
300
|
* The result.
|
|
281
301
|
*
|
|
282
|
-
* @const {
|
|
302
|
+
* @const {Promise<number | undefined>} result
|
|
283
303
|
*/
|
|
284
|
-
const result:
|
|
304
|
+
const result: Promise<number | undefined> = when(value, {
|
|
285
305
|
args: [39],
|
|
286
306
|
chain: divide,
|
|
287
307
|
context: { errors: [] },
|
|
@@ -316,19 +336,83 @@ function fail(this: Context, e: Error): undefined {
|
|
|
316
336
|
}
|
|
317
337
|
```
|
|
318
338
|
|
|
339
|
+
### Integrate with [`@typescript-eslint`][typescript-eslint]
|
|
340
|
+
|
|
341
|
+
```js
|
|
342
|
+
/**
|
|
343
|
+
* The eslint configuration.
|
|
344
|
+
*
|
|
345
|
+
* @type {import('eslint').Linter.Config[]}
|
|
346
|
+
* @const config
|
|
347
|
+
*/
|
|
348
|
+
const config = [
|
|
349
|
+
{
|
|
350
|
+
files: ['**/*.+(cjs|cts|js|jsx|mjs|mts|ts|tsx)'],
|
|
351
|
+
rules: {
|
|
352
|
+
'@typescript-eslint/promise-function-async': [
|
|
353
|
+
2,
|
|
354
|
+
{
|
|
355
|
+
allowedPromiseNames: ['Thenable']
|
|
356
|
+
}
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
]
|
|
361
|
+
|
|
362
|
+
export default config
|
|
363
|
+
```
|
|
364
|
+
|
|
319
365
|
## API
|
|
320
366
|
|
|
321
367
|
`when` exports the identifiers listed below.
|
|
322
368
|
|
|
323
369
|
The default export is [`when`][when].
|
|
324
370
|
|
|
325
|
-
### `
|
|
371
|
+
### `isCatchable<T>(value)`
|
|
372
|
+
|
|
373
|
+
Check if `value` looks like a [`Thenable`][thenable] that can be caught.
|
|
374
|
+
|
|
375
|
+
#### Type Parameters
|
|
376
|
+
|
|
377
|
+
- `T` (`any`)
|
|
378
|
+
— the resolved value
|
|
379
|
+
|
|
380
|
+
#### Parameters
|
|
381
|
+
|
|
382
|
+
- `value` (`unknown`)
|
|
383
|
+
— the thing to check
|
|
384
|
+
|
|
385
|
+
#### Returns
|
|
386
|
+
|
|
387
|
+
([`value is Catchable<T>`][catchable])
|
|
388
|
+
`true` if `value` is a [*thenable*][thenable-term] with a [`catch`][catch] method, `false` otherwise
|
|
389
|
+
|
|
390
|
+
### `isFinalizable<T>(value)`
|
|
391
|
+
|
|
392
|
+
Check if `value` looks like a [`Thenable`][thenable] that can be finalized.
|
|
393
|
+
|
|
394
|
+
#### Type Parameters
|
|
395
|
+
|
|
396
|
+
- `T` (`any`)
|
|
397
|
+
— the resolved value
|
|
398
|
+
|
|
399
|
+
#### Parameters
|
|
400
|
+
|
|
401
|
+
- `value` (`unknown`)
|
|
402
|
+
— the thing to check
|
|
403
|
+
|
|
404
|
+
#### Returns
|
|
405
|
+
|
|
406
|
+
([`value is Finalizable<T>`][finalizable])
|
|
407
|
+
`true` if `value` is a [*thenable*][thenable-term] with a [`finally`][finally] method, `false` otherwise
|
|
408
|
+
|
|
409
|
+
### `isPromise<T>(value[, finalizable])`
|
|
326
410
|
|
|
327
411
|
Check if `value` looks like a `Promise`.
|
|
328
412
|
|
|
329
|
-
> 👉 **Note**: This function intentionally performs
|
|
330
|
-
> It does not rely on `instanceof Promise` or constructors, making it compatible with cross-realm
|
|
331
|
-
> and custom thenables.
|
|
413
|
+
> 👉 **Note**: This function intentionally performs structural checks instead of brand checks.
|
|
414
|
+
> It does not rely on `instanceof Promise` or constructors, making it compatible with cross-realm
|
|
415
|
+
> promises and custom thenables.
|
|
332
416
|
|
|
333
417
|
#### Type Parameters
|
|
334
418
|
|
|
@@ -339,16 +423,38 @@ Check if `value` looks like a `Promise`.
|
|
|
339
423
|
|
|
340
424
|
- `value` (`unknown`)
|
|
341
425
|
— the thing to check
|
|
426
|
+
- `finalizable` (`boolean` | `null` | `undefined`)
|
|
427
|
+
— whether a [`finally`][finally] method is required.\
|
|
428
|
+
when `false`, only [`then`][then] and [`catch`][catch] are checked
|
|
342
429
|
|
|
343
430
|
#### Returns
|
|
344
431
|
|
|
345
|
-
(`value is Promise<T>`)
|
|
432
|
+
(`value is Promise<T>`)
|
|
433
|
+
`true` if `value` is a [*thenable*][thenable-term] with a [`catch`][catch] method,
|
|
434
|
+
and [`finally`][finally] method (if requested), `false` otherwise
|
|
346
435
|
|
|
347
|
-
### `
|
|
436
|
+
### `isPromiseLike<T>(value)`
|
|
437
|
+
|
|
438
|
+
Check if `value` looks like a [`PromiseLike`][promiselike] structure.
|
|
348
439
|
|
|
349
|
-
|
|
440
|
+
#### Type Parameters
|
|
350
441
|
|
|
351
|
-
|
|
442
|
+
- `T` (`any`)
|
|
443
|
+
— the resolved value
|
|
444
|
+
|
|
445
|
+
#### Parameters
|
|
446
|
+
|
|
447
|
+
- `value` (`unknown`)
|
|
448
|
+
— the thing to check
|
|
449
|
+
|
|
450
|
+
#### Returns
|
|
451
|
+
|
|
452
|
+
([`value is PromiseLike<T>`][promiselike])
|
|
453
|
+
`true` if `value` is an object or function with a [`then`][then] method, `false` otherwise
|
|
454
|
+
|
|
455
|
+
### `isThenable<T>(value)`
|
|
456
|
+
|
|
457
|
+
Check if `value` looks like a [*thenable*][thenable-term].
|
|
352
458
|
|
|
353
459
|
#### Type Parameters
|
|
354
460
|
|
|
@@ -362,16 +468,17 @@ Check if `value` looks like a [*thenable*][thenable], i.e. a `PromiseLike` objec
|
|
|
362
468
|
|
|
363
469
|
#### Returns
|
|
364
470
|
|
|
365
|
-
(`value is
|
|
471
|
+
([`value is Thenable<T>`][thenable]) `true` if `value` is an object or function with a [`then`][then] method,
|
|
472
|
+
and maybe-callable methods [`catch`][catch] and/or [`finally`][finally], `false` otherwise
|
|
366
473
|
|
|
367
474
|
<!--lint disable-->
|
|
368
475
|
|
|
369
|
-
### `when<T[, Next][, Failure][, Args][, Error][, This]>(value, chain[, fail][, context][, ...args])`
|
|
476
|
+
### `when<T[, Next][, Failure][, Args][, Error][, This][, Result]>(value, chain[, fail][, context][, ...args])`
|
|
370
477
|
|
|
371
478
|
<!--lint enable-->
|
|
372
479
|
|
|
373
480
|
Chain a callback, calling the function after `value` is resolved,
|
|
374
|
-
or immediately if `value` is not a [*thenable*][thenable].
|
|
481
|
+
or immediately if `value` is not a [*thenable*][thenable-term].
|
|
375
482
|
|
|
376
483
|
#### Overloads
|
|
377
484
|
|
|
@@ -380,7 +487,8 @@ function when<
|
|
|
380
487
|
T,
|
|
381
488
|
Next = any,
|
|
382
489
|
Args extends any[] = any[],
|
|
383
|
-
This = unknown
|
|
490
|
+
This = unknown,
|
|
491
|
+
Result extends Awaitable<Next> = Awaitable<Next>
|
|
384
492
|
>(
|
|
385
493
|
this: void,
|
|
386
494
|
value: Awaitable<T>,
|
|
@@ -388,7 +496,7 @@ function when<
|
|
|
388
496
|
fail?: null | undefined,
|
|
389
497
|
context?: This | null | undefined,
|
|
390
498
|
...args: Args
|
|
391
|
-
):
|
|
499
|
+
): Result
|
|
392
500
|
```
|
|
393
501
|
|
|
394
502
|
```ts
|
|
@@ -398,7 +506,8 @@ function when<
|
|
|
398
506
|
Failure = Next,
|
|
399
507
|
Args extends any[] = any[],
|
|
400
508
|
Error = any,
|
|
401
|
-
This = unknown
|
|
509
|
+
This = unknown,
|
|
510
|
+
Result extends Awaitable<Failure | Next> = Awaitable<Failure | Next>
|
|
402
511
|
>(
|
|
403
512
|
this: void,
|
|
404
513
|
value: Awaitable<T>,
|
|
@@ -406,7 +515,7 @@ function when<
|
|
|
406
515
|
fail?: Fail<Failure, Error, This> | null | undefined,
|
|
407
516
|
context?: This | null | undefined,
|
|
408
517
|
...args: Args
|
|
409
|
-
):
|
|
518
|
+
): Result
|
|
410
519
|
```
|
|
411
520
|
|
|
412
521
|
```ts
|
|
@@ -416,12 +525,13 @@ function when<
|
|
|
416
525
|
Failure = Next,
|
|
417
526
|
Args extends any[] = any[],
|
|
418
527
|
Error = any,
|
|
419
|
-
This = unknown
|
|
528
|
+
This = unknown,
|
|
529
|
+
Result extends Awaitable<Failure | Next> = Awaitable<Failure | Next>
|
|
420
530
|
>(
|
|
421
531
|
this: void,
|
|
422
532
|
value: Awaitable<T>,
|
|
423
533
|
chain: Options<T, Next, Failure, Args, Error, This>
|
|
424
|
-
):
|
|
534
|
+
): Result
|
|
425
535
|
```
|
|
426
536
|
|
|
427
537
|
#### Type Parameters
|
|
@@ -443,6 +553,9 @@ function when<
|
|
|
443
553
|
- `This` (`any`, optional)
|
|
444
554
|
— the `this` context
|
|
445
555
|
- **default**: `unknown`
|
|
556
|
+
- `Result` ([`Awaitable<Failure | Next>`][awaitable], optional)
|
|
557
|
+
— the next awaitable
|
|
558
|
+
- **default**: [`Awaitable<Failure | Next>`][awaitable]
|
|
446
559
|
|
|
447
560
|
#### Parameters
|
|
448
561
|
|
|
@@ -452,7 +565,7 @@ function when<
|
|
|
452
565
|
— the chain callback or options for chaining
|
|
453
566
|
- `fail` ([`Fail<Failure, Error, This>`][fail] | `null` | `undefined`)
|
|
454
567
|
— the callback to fire when a failure occurs. failures include:
|
|
455
|
-
- rejections of the input [*thenable*][thenable]
|
|
568
|
+
- rejections of the input [*thenable*][thenable-term]
|
|
456
569
|
- rejections returned from `chain`
|
|
457
570
|
- synchronous errors thrown in `chain`\
|
|
458
571
|
if no `fail` handler is provided, failures are re-thrown or re-propagated.
|
|
@@ -467,16 +580,78 @@ function when<
|
|
|
467
580
|
|
|
468
581
|
([`Awaitable<Failure | Next>`][awaitable] | [`Awaitable<Next>`][awaitable]) The next [*awaitable*][awaitable-term]
|
|
469
582
|
|
|
583
|
+
## Testing
|
|
584
|
+
|
|
585
|
+
Test utilities are exported from `@flex-development/when/testing`.
|
|
586
|
+
|
|
587
|
+
There is no default export.
|
|
588
|
+
|
|
589
|
+
```ts
|
|
590
|
+
import {
|
|
591
|
+
isCatchable,
|
|
592
|
+
isFinalizable,
|
|
593
|
+
type Thenable
|
|
594
|
+
} from '@flex-development/when'
|
|
595
|
+
import { createThenable } from '@flex-development/when/testing'
|
|
596
|
+
import { ok } from 'devlop'
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* The thenable.
|
|
600
|
+
*
|
|
601
|
+
* @const {Thenable<number>} thenable
|
|
602
|
+
*/
|
|
603
|
+
const thenable: Thenable<number> = createThenable(resolve => resolve(10))
|
|
604
|
+
|
|
605
|
+
ok(isCatchable(thenable), 'expected `thenable` to be a catchable')
|
|
606
|
+
ok(isFinalizable(thenable), 'expected `thenable` to be a finalizable')
|
|
607
|
+
|
|
608
|
+
console.dir(await thenable.then(value => value + 3)) // 13
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
### `createThenable<T[, Reason][, Result]>(executor[, options])`
|
|
612
|
+
|
|
613
|
+
Create a thenable.
|
|
614
|
+
|
|
615
|
+
The returned object conforms to [`Thenable`][thenable] and ensures [`then`][then] always returns another `Thenable`,
|
|
616
|
+
even when adopting a foreign [*thenable*][thenable-term].
|
|
617
|
+
|
|
618
|
+
When `options` is omitted, `null`, or `undefined`, the returned thenable is *modern* (a [*thenable*][thenable-term]
|
|
619
|
+
with [`then`][then], [`catch`][catch], and [`finally`][finally] methods).
|
|
620
|
+
Pass an options object (e.g. `{}`) to start from a *bare* ([`then`][then] method only) thenable
|
|
621
|
+
and selectively enable methods.
|
|
622
|
+
|
|
623
|
+
#### Type Parameters
|
|
624
|
+
|
|
625
|
+
- `T` (`any`)
|
|
626
|
+
— the resolved value
|
|
627
|
+
- `Reason` (`any`, optional)
|
|
628
|
+
— the reason for a rejection
|
|
629
|
+
- **default**: `Error`
|
|
630
|
+
- `Result` ([`Thenable<T>`][thenable], optional)
|
|
631
|
+
— the thenable
|
|
632
|
+
- **default**: [`Thenable<T>`][thenable]
|
|
633
|
+
|
|
634
|
+
#### Parameters
|
|
635
|
+
|
|
636
|
+
- `executor` ([`Executor<T, Reason>`][executor])
|
|
637
|
+
— the initialization callback
|
|
638
|
+
- `options` ([`CreateThenableOptions`][createthenableoptions] | `null` | `undefined`, optional)
|
|
639
|
+
— options for creating a thenable
|
|
640
|
+
|
|
641
|
+
#### Returns
|
|
642
|
+
|
|
643
|
+
(`Result`) The [*thenable*][thenable-term]
|
|
644
|
+
|
|
470
645
|
## Types
|
|
471
646
|
|
|
472
647
|
This package is fully typed with [TypeScript][].
|
|
473
648
|
|
|
474
649
|
### `Awaitable<T>`
|
|
475
650
|
|
|
476
|
-
A synchronous or [*thenable*][thenable] value (`type`).
|
|
651
|
+
A synchronous or [*thenable*][thenable-term] value (`type`).
|
|
477
652
|
|
|
478
653
|
```ts
|
|
479
|
-
type Awaitable<T> =
|
|
654
|
+
type Awaitable<T> = Thenable<T> | T
|
|
480
655
|
```
|
|
481
656
|
|
|
482
657
|
#### Type Parameters
|
|
@@ -484,6 +659,57 @@ type Awaitable<T> = PromiseLike<T> | T
|
|
|
484
659
|
- `T` (`any`)
|
|
485
660
|
— the resolved value
|
|
486
661
|
|
|
662
|
+
### `Catch<[T][, Reason]>`
|
|
663
|
+
|
|
664
|
+
Attach a callback only for the rejection of a [`Thenable`][thenable] (`type`).
|
|
665
|
+
|
|
666
|
+
```ts
|
|
667
|
+
type Catch<T = unknown, Reason = any> = <Next = never>(
|
|
668
|
+
this: any,
|
|
669
|
+
onrejected?: OnRejected<Next, Reason> | null | undefined
|
|
670
|
+
) => Thenable<Next | T>
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
#### Type Parameters
|
|
674
|
+
|
|
675
|
+
- `T` (`any`, optional)
|
|
676
|
+
— the resolved value
|
|
677
|
+
- **default**: `unknown`
|
|
678
|
+
- `Reason` (`any`, optional)
|
|
679
|
+
— the reason for the rejection
|
|
680
|
+
- **default**: `any`
|
|
681
|
+
- `Next` (`any`, optional)
|
|
682
|
+
— the next resolved value
|
|
683
|
+
- **default**: `never`
|
|
684
|
+
|
|
685
|
+
#### Parameters
|
|
686
|
+
|
|
687
|
+
- `onrejected` ([`OnRejected<Next, Reason>`][onrejected] | `null` | `undefined`)
|
|
688
|
+
— the callback to execute when the thenable is rejected
|
|
689
|
+
|
|
690
|
+
#### Returns
|
|
691
|
+
|
|
692
|
+
([`Thenable<Next | T>`][thenable]) The next [*thenable*][thenable-term]
|
|
693
|
+
|
|
694
|
+
### `Catchable<[T]>`
|
|
695
|
+
|
|
696
|
+
A [`Thenable`][thenable] that can be caught (`interface`).
|
|
697
|
+
|
|
698
|
+
#### Extends
|
|
699
|
+
|
|
700
|
+
- [`Thenable<T>`][thenable]
|
|
701
|
+
|
|
702
|
+
#### Type Parameters
|
|
703
|
+
|
|
704
|
+
- `T` (`any`, optional)
|
|
705
|
+
— the resolved value
|
|
706
|
+
- **default**: `any`
|
|
707
|
+
|
|
708
|
+
#### Properties
|
|
709
|
+
|
|
710
|
+
- `catch` ([`Catch<T>`][catch])
|
|
711
|
+
— attach a callback only to be invoked on rejection
|
|
712
|
+
|
|
487
713
|
### `Chain<[T][, Next][, Args][, This]>`
|
|
488
714
|
|
|
489
715
|
A chain callback (`type`).
|
|
@@ -523,16 +749,71 @@ type Chain<
|
|
|
523
749
|
|
|
524
750
|
([`Awaitable<Next>`][awaitable]) The next [*awaitable*][awaitable-term]
|
|
525
751
|
|
|
526
|
-
### `
|
|
752
|
+
### `CreateThenableOptions`
|
|
753
|
+
|
|
754
|
+
Options for creating a [*thenable*][thenable-term] (`interface`).
|
|
755
|
+
|
|
756
|
+
> 👉 **Note**: Exported from `@flex-development/when/testing` only.
|
|
757
|
+
|
|
758
|
+
#### Properties
|
|
759
|
+
|
|
760
|
+
- `catch?` (`boolean` | `null` | `undefined`)
|
|
761
|
+
— control whether returned thenables implement a [`catch`][catch] method.\
|
|
762
|
+
when an options object is omitted, `null`, or `undefined`, the method will be implemented.\<br/>
|
|
763
|
+
when an options object is provided, `catch` is only implemented if `options.catch` is `true`.\
|
|
764
|
+
if `options.catch` is `null` or `undefined`, the thenable's `catch` property will have the same value.\
|
|
765
|
+
pass `false` to disable the method implementation
|
|
766
|
+
- `finally?` (`boolean` | `null` | `undefined`)
|
|
767
|
+
— control whether returned thenables implement a [`finally`][finally] method.\
|
|
768
|
+
when an options object is omitted, `null`, or `undefined`, the method will be implemented.\
|
|
769
|
+
when an options object is provided, `finally` is only implemented if `options.finally` is `true`.\
|
|
770
|
+
if `options.finally` is `null` or `undefined`, the thenable's `finally` property will have the same value.\
|
|
771
|
+
pass `false` to disable the method implementation
|
|
772
|
+
|
|
773
|
+
### `Executor<[T][, Reason]>`
|
|
774
|
+
|
|
775
|
+
The callback used to initialize a [*thenable*][thenable-term] (`type`).
|
|
776
|
+
|
|
777
|
+
> 👉 **Note**: Exported from `@flex-development/when/testing` only.
|
|
778
|
+
|
|
779
|
+
```ts
|
|
780
|
+
type Executor<T = any, Reason = Error> = (
|
|
781
|
+
this: void,
|
|
782
|
+
resolve: Resolve<T>,
|
|
783
|
+
reject: Reject<Reason>
|
|
784
|
+
) => undefined | void
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
#### Type Parameters
|
|
788
|
+
|
|
789
|
+
- `T` (`any`, optional)
|
|
790
|
+
— the resolved value
|
|
791
|
+
- **default**: `any`
|
|
792
|
+
- `Reason` (`any`, optional)
|
|
793
|
+
— the reason for a rejection
|
|
794
|
+
- **default**: `Error`
|
|
795
|
+
|
|
796
|
+
#### Parameters
|
|
797
|
+
|
|
798
|
+
- `resolve` ([`Resolve<T>`][resolve])
|
|
799
|
+
— the callback used to resolve the thenable with a value or the result of another [*awaitable*][awaitable-term]
|
|
800
|
+
- `reject` ([`Reject<Reason>`][reject])
|
|
801
|
+
— the callback used to reject the thenable with a provided reason or error
|
|
802
|
+
|
|
803
|
+
#### Returns
|
|
804
|
+
|
|
805
|
+
(`undefined` | `void`) Nothing
|
|
806
|
+
|
|
807
|
+
### `Fail<[Next][, Reason][, This]>`
|
|
527
808
|
|
|
528
809
|
The callback to fire when a failure occurs (`type`).
|
|
529
810
|
|
|
530
811
|
```ts
|
|
531
812
|
type Fail<
|
|
532
813
|
Next = any,
|
|
533
|
-
|
|
814
|
+
Reason = any,
|
|
534
815
|
This = unknown
|
|
535
|
-
> = (this: This,
|
|
816
|
+
> = (this: This, reason: Reason) => Awaitable<Next>
|
|
536
817
|
```
|
|
537
818
|
|
|
538
819
|
#### Type Parameters
|
|
@@ -540,8 +821,8 @@ type Fail<
|
|
|
540
821
|
- `Next` (`any`, optional)
|
|
541
822
|
— the next resolved value
|
|
542
823
|
- **default**: `any`
|
|
543
|
-
- `
|
|
544
|
-
— the
|
|
824
|
+
- `Reason` (`any`, optional)
|
|
825
|
+
— the reason for the failure
|
|
545
826
|
- **default**: `any`
|
|
546
827
|
- `This` (`any`, optional)
|
|
547
828
|
— the `this` context
|
|
@@ -550,8 +831,141 @@ type Fail<
|
|
|
550
831
|
#### Parameters
|
|
551
832
|
|
|
552
833
|
- **`this`** (`This`)
|
|
553
|
-
- `
|
|
554
|
-
— the
|
|
834
|
+
- `reason` (`Reason`)
|
|
835
|
+
— the reason for the failure
|
|
836
|
+
|
|
837
|
+
#### Returns
|
|
838
|
+
|
|
839
|
+
([`Awaitable<Next>`][awaitable]) The next [*awaitable*][awaitable-term]
|
|
840
|
+
|
|
841
|
+
### `Finalizable<[T]>`
|
|
842
|
+
|
|
843
|
+
A [`Thenable`][thenable] that can be finalized (`interface`).
|
|
844
|
+
|
|
845
|
+
#### Extends
|
|
846
|
+
|
|
847
|
+
- [`Thenable<T>`][thenable]
|
|
848
|
+
|
|
849
|
+
#### Type Parameters
|
|
850
|
+
|
|
851
|
+
- `T` (`any`, optional)
|
|
852
|
+
— the resolved value
|
|
853
|
+
- **default**: `any`
|
|
854
|
+
|
|
855
|
+
#### Properties
|
|
856
|
+
|
|
857
|
+
- `finally` ([`Finally<T>`][finally])
|
|
858
|
+
— attach a callback only to be invoked on settlement (fulfillment or rejection)
|
|
859
|
+
> 👉 **note**: the resolved value cannot be modified from the callback
|
|
860
|
+
|
|
861
|
+
### `Finally<[T]>`
|
|
862
|
+
|
|
863
|
+
Attach a callback that is invoked only when a [`Thenable`][thenable] is settled (fulfilled or rejected) (`type`).
|
|
864
|
+
|
|
865
|
+
```ts
|
|
866
|
+
type Finally<T = unknown> = (
|
|
867
|
+
this: any,
|
|
868
|
+
onfinally?: OnFinally | null | undefined
|
|
869
|
+
) => Thenable<T>
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
#### Type Parameters
|
|
873
|
+
|
|
874
|
+
- `T` (`any`, optional)
|
|
875
|
+
— the resolved value
|
|
876
|
+
- **default**: `unknown`
|
|
877
|
+
|
|
878
|
+
#### Parameters
|
|
879
|
+
|
|
880
|
+
- `onfinally` ([`OnFinally`][onfinally] | `null` | `undefined`)
|
|
881
|
+
— the callback to execute when the thenable is settled
|
|
882
|
+
|
|
883
|
+
#### Returns
|
|
884
|
+
|
|
885
|
+
([`Thenable<T>`][thenable]) The next [*thenable*][thenable-term]
|
|
886
|
+
|
|
887
|
+
### `Finish<[This]>`
|
|
888
|
+
|
|
889
|
+
A post-processing hook invoked exactly once after an [*awaitable*][awaitable-term] settles,
|
|
890
|
+
regardless of success or failure (`type`).
|
|
891
|
+
|
|
892
|
+
The resolved value cannot be modified from the hook, and any error is re-thrown after execution.
|
|
893
|
+
|
|
894
|
+
```ts
|
|
895
|
+
type Finish<This = unknown> = (this: This) => undefined | void
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
#### Type Parameters
|
|
899
|
+
|
|
900
|
+
- `This` (`any`, optional)
|
|
901
|
+
— the `this` context
|
|
902
|
+
- **default**: `unknown`
|
|
903
|
+
|
|
904
|
+
#### Returns
|
|
905
|
+
|
|
906
|
+
(`undefined` | `void`) Nothing
|
|
907
|
+
|
|
908
|
+
### `OnFinally`
|
|
909
|
+
|
|
910
|
+
The callback to execute when a [`Thenable`][thenable] is settled (fulfilled or rejected) (`type`).
|
|
911
|
+
|
|
912
|
+
```ts
|
|
913
|
+
type OnFinally = (this: unknown) => undefined | void
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
#### Returns
|
|
917
|
+
|
|
918
|
+
(`undefined` | `void`) Nothing
|
|
919
|
+
|
|
920
|
+
### `OnFulfilled<T[, Next]>`
|
|
921
|
+
|
|
922
|
+
The callback to execute when a [`Thenable`][thenable] is resolved (`type`).
|
|
923
|
+
|
|
924
|
+
```ts
|
|
925
|
+
type OnFulfilled<T, Next = T> = (this: unknown, value: T) => Awaitable<Next>
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
#### Type Parameters
|
|
929
|
+
|
|
930
|
+
- `T` (`any`)
|
|
931
|
+
— the resolved value
|
|
932
|
+
- `Next` (`any`, optional)
|
|
933
|
+
— the next resolved value
|
|
934
|
+
- **default**: `T`
|
|
935
|
+
|
|
936
|
+
#### Parameters
|
|
937
|
+
|
|
938
|
+
- `value` (`T`)
|
|
939
|
+
— the resolved value
|
|
940
|
+
|
|
941
|
+
#### Returns
|
|
942
|
+
|
|
943
|
+
([`Awaitable<Next>`][awaitable]) The next [*awaitable*][awaitable-term]
|
|
944
|
+
|
|
945
|
+
### `OnRejected<Next[, Reason]>`
|
|
946
|
+
|
|
947
|
+
The callback to execute when a [`Thenable`][thenable] is rejected (`type`).
|
|
948
|
+
|
|
949
|
+
```ts
|
|
950
|
+
type OnRejected<
|
|
951
|
+
Next,
|
|
952
|
+
Reason = any
|
|
953
|
+
> = (this: unknown, reason: Reason) => Awaitable<Next>
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
#### Type Parameters
|
|
957
|
+
|
|
958
|
+
- `Next` (`any`, optional)
|
|
959
|
+
— the next resolved value
|
|
960
|
+
- **default**: `any`
|
|
961
|
+
- `Reason` (`any`, optional)
|
|
962
|
+
— the reason for the rejection
|
|
963
|
+
- **default**: `any`
|
|
964
|
+
|
|
965
|
+
#### Parameters
|
|
966
|
+
|
|
967
|
+
- `reason` (`Reason`)
|
|
968
|
+
— the reason for the rejection
|
|
555
969
|
|
|
556
970
|
#### Returns
|
|
557
971
|
|
|
@@ -603,29 +1017,163 @@ interface Options<
|
|
|
603
1017
|
— the `this` context of the `chain` and `fail` callbacks
|
|
604
1018
|
- `fail?` ([`Fail<Next, Error, This>`][fail] | `null` | `undefined`)
|
|
605
1019
|
— the callback to fire when a failure occurs. failures include:
|
|
606
|
-
- rejections of the input [*thenable*][thenable]
|
|
1020
|
+
- rejections of the input [*thenable*][thenable-term]
|
|
607
1021
|
- rejections returned from `chain`
|
|
608
1022
|
- synchronous errors thrown in `chain`\
|
|
609
1023
|
if no `fail` handler is provided, failures are re-thrown or re-propagated.
|
|
610
1024
|
> 👉 **note**: for thenables, this callback is passed to `then` as the `onrejected` parameter,
|
|
611
|
-
> and if implemented, to `catch` as well to prevent unhandled rejections.
|
|
1025
|
+
> and if implemented, to [`catch`][catch] as well to prevent unhandled rejections.
|
|
1026
|
+
- `finish?` ([`Finish<This>`][finish] | `null` | `undefined`)
|
|
1027
|
+
— the callback to invoke after chaining completes, whether the operation succeeds or fails.\
|
|
1028
|
+
it runs exactly once after `chain` and `fail`, cannot affect the resolved value, and does not intercept errors
|
|
1029
|
+
|
|
1030
|
+
### `PromiseLike<T>`
|
|
1031
|
+
|
|
1032
|
+
To ensure native `Promise` and `PromiseLike` are assignable to [`Thenable`][thenable],
|
|
1033
|
+
`when` ships a small global augmentation for `PromiseLike`.
|
|
1034
|
+
|
|
1035
|
+
No new methods or overloads are introduced — the `then` signature is rewritten to match
|
|
1036
|
+
the official [TypeScript][] lib definition (as in `lib.es2015.d.ts`).
|
|
1037
|
+
|
|
1038
|
+
This is required for both compatibility, and type inference when mixing `Thenable` with built-in promise types.
|
|
1039
|
+
|
|
1040
|
+
#### Type Parameters
|
|
1041
|
+
|
|
1042
|
+
- `T` (`any`)
|
|
1043
|
+
— the resolved value
|
|
1044
|
+
|
|
1045
|
+
### `Reject<[Reason]>`
|
|
1046
|
+
|
|
1047
|
+
The callback used to reject a [*thenable*][thenable-term] with a provided reason or error (`type`).
|
|
1048
|
+
|
|
1049
|
+
> 👉 **Note**: Exported from `@flex-development/when/testing` only.
|
|
1050
|
+
|
|
1051
|
+
```ts
|
|
1052
|
+
type Reject<Reason = Error> = (this: void, reason: Reason) => undefined
|
|
1053
|
+
```
|
|
1054
|
+
|
|
1055
|
+
#### Type Parameters
|
|
1056
|
+
|
|
1057
|
+
- `Reason` (`any`, optional)
|
|
1058
|
+
— the reason for the rejection
|
|
1059
|
+
- **default**: `Error`
|
|
1060
|
+
|
|
1061
|
+
#### Parameters
|
|
1062
|
+
|
|
1063
|
+
- `reason` (`Reason`)
|
|
1064
|
+
— the reason for the rejection
|
|
1065
|
+
|
|
1066
|
+
#### Returns
|
|
1067
|
+
|
|
1068
|
+
(`undefined`) Nothing
|
|
1069
|
+
|
|
1070
|
+
### `Resolve<[T]>`
|
|
1071
|
+
|
|
1072
|
+
The callback used to resolve a [*thenable*][thenable-term] with a value
|
|
1073
|
+
or the result of another [*awaitable*][awaitable-term] (`type`).
|
|
1074
|
+
|
|
1075
|
+
> 👉 **Note**: Exported from `@flex-development/when/testing` only.
|
|
1076
|
+
|
|
1077
|
+
```ts
|
|
1078
|
+
type Resolve<T = any> = (this: void, value: Awaitable<T>) => undefined
|
|
1079
|
+
```
|
|
1080
|
+
|
|
1081
|
+
#### Type Parameters
|
|
1082
|
+
|
|
1083
|
+
- `T` (`any`, optional)
|
|
1084
|
+
— the resolved value
|
|
1085
|
+
- **default**: `any`
|
|
1086
|
+
|
|
1087
|
+
#### Parameters
|
|
1088
|
+
|
|
1089
|
+
- `value` ([`Awaitable<T>`][awaitable])
|
|
1090
|
+
— the awaitable
|
|
1091
|
+
|
|
1092
|
+
#### Returns
|
|
1093
|
+
|
|
1094
|
+
(`undefined`) Nothing
|
|
1095
|
+
|
|
1096
|
+
### `Then<T[, Reason]>`
|
|
1097
|
+
|
|
1098
|
+
Attach callbacks for the resolution and/or rejection of a [`Thenable`][thenable] (`type`).
|
|
1099
|
+
|
|
1100
|
+
```ts
|
|
1101
|
+
type Then<T = unknown, Reason = any> = <Succ = T, Fail = never>(
|
|
1102
|
+
this: any,
|
|
1103
|
+
onfulfilled?: OnFulfilled<T, Succ> | null | undefined,
|
|
1104
|
+
onrejected?: OnRejected<Fail, Reason> | null | undefined
|
|
1105
|
+
) => Thenable<Fail | Succ>
|
|
1106
|
+
```
|
|
1107
|
+
|
|
1108
|
+
#### Type Parameters
|
|
1109
|
+
|
|
1110
|
+
- `T` (`any`, optional)
|
|
1111
|
+
— the previously resolved value
|
|
1112
|
+
- **default**: `unknown`
|
|
1113
|
+
- `Reason` (`any`, optional)
|
|
1114
|
+
— the reason for a rejection
|
|
1115
|
+
- **default**: `any`
|
|
1116
|
+
- `Succ` (`any`, optional)
|
|
1117
|
+
— the next resolved value on success
|
|
1118
|
+
- **default**: `T`
|
|
1119
|
+
- `Fail` (`any`, optional)
|
|
1120
|
+
— the next resolved value on failure
|
|
1121
|
+
- **default**: `never`
|
|
1122
|
+
|
|
1123
|
+
#### Parameters
|
|
1124
|
+
|
|
1125
|
+
- `onfulfilled` ([`OnFulfilled<T, Succ>`][onfulfilled] | `null` | `undefined`)
|
|
1126
|
+
— the callback to execute when the thenable is resolved
|
|
1127
|
+
- `onrejected` ([`OnRejected<Fail, Reason>`][onrejected] | `null` | `undefined`)
|
|
1128
|
+
— the callback to execute when the thenable is rejected
|
|
1129
|
+
|
|
1130
|
+
#### Returns
|
|
1131
|
+
|
|
1132
|
+
([`Thenable<Fail | Succ>`][thenable]) The next [*thenable*][thenable-term]
|
|
1133
|
+
|
|
1134
|
+
### `Thenable<[T]>`
|
|
1135
|
+
|
|
1136
|
+
The completion of an asynchronous operation, and the minimal structural contract required
|
|
1137
|
+
by [`when`][when] to treat a value as asynchronous (`interface`).
|
|
1138
|
+
|
|
1139
|
+
Unlike `PromiseLike`, this interface allows a maybe-callable [`catch`][catch] method, which when present,
|
|
1140
|
+
is used by [`when`][when] to ensure failures are handled without forcing promise allocation.
|
|
1141
|
+
|
|
1142
|
+
Maybe-callable methods are named so because they are not required,
|
|
1143
|
+
and may be a method implementation, `null`, or `undefined`.
|
|
1144
|
+
|
|
1145
|
+
#### Type Parameters
|
|
1146
|
+
|
|
1147
|
+
- `T` (`any`, optional)
|
|
1148
|
+
— the resolved value
|
|
1149
|
+
- **default**: `any`
|
|
1150
|
+
|
|
1151
|
+
#### Properties
|
|
1152
|
+
|
|
1153
|
+
- `catch?` ([`Catch<T>`][catch] | `null` | `undefined`)
|
|
1154
|
+
— attach a callback only to be invoked on rejection
|
|
1155
|
+
- `then` ([`Then<T>`][then])
|
|
1156
|
+
— attach callbacks to be invoked on resolution (fulfillment) and/or rejection
|
|
1157
|
+
- `finally?` ([`Finally<T>`][finally] | `null` | `undefined`)
|
|
1158
|
+
— attach a callback only to be invoked on settlement (fulfillment or rejection)
|
|
1159
|
+
> 👉 **note**: the resolved value cannot be modified from the callback
|
|
612
1160
|
|
|
613
1161
|
## Glossary
|
|
614
1162
|
|
|
615
1163
|
### *awaitable*
|
|
616
1164
|
|
|
617
|
-
A synchronous or [*thenable*][thenable] value.
|
|
1165
|
+
A synchronous or [*thenable*][thenable-term] value.
|
|
618
1166
|
|
|
619
1167
|
### *thenable*
|
|
620
1168
|
|
|
621
|
-
An object or function with a `then` method.
|
|
1169
|
+
An object or function with a [`then`][then] method.
|
|
622
1170
|
|
|
623
1171
|
JavaScript engines use duck-typing for promises.
|
|
624
1172
|
Arrays, functions, and objects with a `then` method will be treated as promise-like objects, and work with built-in
|
|
625
1173
|
mechanisms like [`Promise.resolve`][promise-resolve] and the [`await` keyword][await] like native promises.
|
|
626
1174
|
|
|
627
|
-
Some thenables also implement a `catch` method (like native promises).
|
|
628
|
-
When available, `when` uses it to ensure rejections are handled.
|
|
1175
|
+
Some thenables also implement a [`catch`][catch] method (like native promises).
|
|
1176
|
+
When available, [`when`][when] uses it to ensure rejections are handled.
|
|
629
1177
|
|
|
630
1178
|
## Project
|
|
631
1179
|
|
|
@@ -653,30 +1201,70 @@ Support long-term stability by sponsoring Flex Development.
|
|
|
653
1201
|
|
|
654
1202
|
[awaitable]: #awaitablet
|
|
655
1203
|
|
|
1204
|
+
[catch]: #catcht-reason
|
|
1205
|
+
|
|
1206
|
+
[catchable]: #catchablet
|
|
1207
|
+
|
|
656
1208
|
[chain]: #chaint-next-args-this
|
|
657
1209
|
|
|
1210
|
+
[createthenable]: #createthenablet-reason-resultexecutor-options
|
|
1211
|
+
|
|
1212
|
+
[createthenableoptions]: #createthenableoptions
|
|
1213
|
+
|
|
658
1214
|
[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
|
|
659
1215
|
|
|
660
1216
|
[esmsh]: https://esm.sh
|
|
661
1217
|
|
|
662
|
-
[
|
|
1218
|
+
[executor]: #executort-reason
|
|
1219
|
+
|
|
1220
|
+
[fail]: #failnext-reason-this
|
|
1221
|
+
|
|
1222
|
+
[finalizable]: #finalizablet
|
|
1223
|
+
|
|
1224
|
+
[finally]: #finallyt
|
|
1225
|
+
|
|
1226
|
+
[finish]: #finishthis
|
|
1227
|
+
|
|
1228
|
+
[iscatchable]: #iscatchabletvalue
|
|
1229
|
+
|
|
1230
|
+
[isfinalizable]: #isfinalizabletvalue
|
|
663
1231
|
|
|
664
|
-
[ispromise]: #ispromisetvalue
|
|
1232
|
+
[ispromise]: #ispromisetvalue-finalizable
|
|
1233
|
+
|
|
1234
|
+
[ispromiselike]: #ispromiseliketvalue
|
|
665
1235
|
|
|
666
1236
|
[isthenable]: #isthenabletvalue
|
|
667
1237
|
|
|
1238
|
+
[onfinally]: #onfinally
|
|
1239
|
+
|
|
1240
|
+
[onfulfilled]: #onfulfilledt-next
|
|
1241
|
+
|
|
1242
|
+
[onrejected]: #onrejectednext-reason
|
|
1243
|
+
|
|
668
1244
|
[options]: #optionst-next-failure-args-error-this
|
|
669
1245
|
|
|
670
1246
|
[promise-resolve]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve
|
|
671
1247
|
|
|
672
1248
|
[promise-then]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise/then
|
|
673
1249
|
|
|
1250
|
+
[promiselike]: #promiseliket
|
|
1251
|
+
|
|
1252
|
+
[reject]: #rejectreason
|
|
1253
|
+
|
|
1254
|
+
[resolve]: #resolvet
|
|
1255
|
+
|
|
674
1256
|
[semver]: https://semver.org
|
|
675
1257
|
|
|
676
|
-
[
|
|
1258
|
+
[then]: #thent-reason
|
|
1259
|
+
|
|
1260
|
+
[thenable-term]: #thenable
|
|
1261
|
+
|
|
1262
|
+
[thenable]: #thenablet
|
|
1263
|
+
|
|
1264
|
+
[typescript-eslint]: https://typescript-eslint.io
|
|
677
1265
|
|
|
678
1266
|
[typescript]: https://www.typescriptlang.org
|
|
679
1267
|
|
|
680
|
-
[when]: #whent-next-failure-args-error-
|
|
1268
|
+
[when]: #whent-next-failure-args-error-this-resultvalue-chain-fail-context-args
|
|
681
1269
|
|
|
682
1270
|
[yarn]: https://yarnpkg.com
|