@handy-common-utils/promise-utils 1.2.7 → 1.4.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/README.md +339 -120
- package/dist/promise-utils.d.ts +47 -32
- package/dist/promise-utils.d.ts.map +1 -1
- package/dist/promise-utils.js +57 -39
- package/package.json +14 -9
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @handy-common-utils/promise-utils
|
|
2
2
|
|
|
3
3
|
These Promise related utilities have 100% test coverage. The package is tiny because there is no dependency on any other package.
|
|
4
|
-
Functions provided are `repeat`, `withRetry`, `inParallel`, `delayedResolve`, `delayedReject`, `
|
|
4
|
+
Functions provided are `repeat`, `withRetry`, `inParallel`, `delayedResolve`, `delayedReject`, `timeoutResolve`, `timeoutReject`, `promiseState`, `synchronized`, etc.
|
|
5
5
|
|
|
6
6
|
[](https://npmjs.org/package/@handy-common-utils/promise-utils)
|
|
7
7
|
[](https://npmjs.org/package/@handy-common-utils/promise-utils)
|
|
@@ -76,38 +76,16 @@ await inParallel(5, topicArns, async topicArn => {
|
|
|
76
76
|
<!-- API start -->
|
|
77
77
|
<a name="readmemd"></a>
|
|
78
78
|
|
|
79
|
-
@handy-common-utils/promise-utils
|
|
80
|
-
|
|
81
79
|
## @handy-common-utils/promise-utils
|
|
82
80
|
|
|
83
|
-
###
|
|
84
|
-
|
|
85
|
-
#### Enumerations
|
|
81
|
+
### Enumerations
|
|
86
82
|
|
|
87
83
|
- [PromiseState](#enumspromisestatemd)
|
|
88
84
|
|
|
89
|
-
|
|
85
|
+
### Classes
|
|
90
86
|
|
|
91
87
|
- [PromiseUtils](#classespromiseutilsmd)
|
|
92
88
|
|
|
93
|
-
#### Variables
|
|
94
|
-
|
|
95
|
-
- [EXPONENTIAL\_SEQUENCE](#exponential_sequence)
|
|
96
|
-
- [FIBONACCI\_SEQUENCE](#fibonacci_sequence)
|
|
97
|
-
|
|
98
|
-
#### Functions
|
|
99
|
-
|
|
100
|
-
- [delayedReject](#delayedreject)
|
|
101
|
-
- [delayedResolve](#delayedresolve)
|
|
102
|
-
- [inParallel](#inparallel)
|
|
103
|
-
- [promiseState](#promisestate)
|
|
104
|
-
- [repeat](#repeat)
|
|
105
|
-
- [synchronised](#synchronised)
|
|
106
|
-
- [synchronized](#synchronized)
|
|
107
|
-
- [timeoutReject](#timeoutreject)
|
|
108
|
-
- [timeoutResolve](#timeoutresolve)
|
|
109
|
-
- [withRetry](#withretry)
|
|
110
|
-
|
|
111
89
|
### Variables
|
|
112
90
|
|
|
113
91
|
#### EXPONENTIAL\_SEQUENCE
|
|
@@ -117,19 +95,19 @@ await inParallel(5, topicArns, async topicArn => {
|
|
|
117
95
|
Array of 25 exponential numbers starting from 1 up to 33554432.
|
|
118
96
|
It can be used to form your own backoff interval array.
|
|
119
97
|
|
|
120
|
-
**`
|
|
121
|
-
```javascript
|
|
98
|
+
**`Example`**
|
|
122
99
|
|
|
100
|
+
```ts
|
|
123
101
|
// 1ms, 2ms, 4ms, 8ms, 16ms, 32ms
|
|
124
102
|
PromiseUtils.withRetry(() => doSomething(), EXPONENTIAL_SEQUENCE.slice(0, 5), err => err.statusCode === 429);
|
|
125
103
|
// 1s, 2s, 4s, 8s, 10s, 10s, 10s, 10s, 10s, 10s
|
|
126
104
|
PromiseUtils.withRetry(() => doSomething(), Array.from({length: 10}, (_v, i) => 1000 * Math.min(EXPONENTIAL_SEQUENCE[i], 10)), err => err.statusCode === 429);
|
|
127
105
|
// with +-10% randomness: 1s, 2s, 4s, 8s
|
|
128
106
|
PromiseUtils.withRetry(() => doSomething(), FIBONACCI_SEQUENCE.slice(0, 4).map(n => 1000 * n * (1 + (Math.random() - 0.5) / 5)), err => err.statusCode === 429);
|
|
107
|
+
```
|
|
129
108
|
|
|
130
109
|
___
|
|
131
110
|
|
|
132
|
-
```
|
|
133
111
|
#### FIBONACCI\_SEQUENCE
|
|
134
112
|
|
|
135
113
|
• `Const` **FIBONACCI\_SEQUENCE**: `number`[]
|
|
@@ -137,43 +115,282 @@ ___
|
|
|
137
115
|
Array of 25 Fibonacci numbers starting from 1 up to 317811.
|
|
138
116
|
It can be used to form your own backoff interval array.
|
|
139
117
|
|
|
140
|
-
**`
|
|
141
|
-
```javascript
|
|
118
|
+
**`Example`**
|
|
142
119
|
|
|
120
|
+
```ts
|
|
143
121
|
// 1ms, 2ms, 3ms, 5ms, 8ms, 13ms
|
|
144
122
|
PromiseUtils.withRetry(() => doSomething(), FIBONACCI_SEQUENCE.slice(0, 5), err => err.statusCode === 429);
|
|
145
123
|
// 1s, 2s, 3s, 4s, 8s, 10s, 10s, 10s, 10s, 10s
|
|
146
124
|
PromiseUtils.withRetry(() => doSomething(), Array.from({length: 10}, (_v, i) => 1000 * Math.min(FIBONACCI_SEQUENCE[i], 10)), err => err.statusCode === 429);
|
|
147
125
|
// with +-10% randomness: 1s, 2s, 3s, 5s, 8s, 13s
|
|
148
126
|
PromiseUtils.withRetry(() => doSomething(), FIBONACCI_SEQUENCE.slice(0, 5).map(n => 1000 * n * (1 + (Math.random() - 0.5) / 5)), err => err.statusCode === 429);
|
|
127
|
+
```
|
|
149
128
|
|
|
150
|
-
|
|
129
|
+
### Functions
|
|
151
130
|
|
|
131
|
+
#### delayedReject
|
|
152
132
|
|
|
153
|
-
|
|
133
|
+
▸ **delayedReject**<`T`, `R`\>(`ms`, `reason`): `Promise`<`T`\>
|
|
154
134
|
|
|
155
|
-
[
|
|
135
|
+
See [delayedReject](#delayedreject) for full documentation.
|
|
156
136
|
|
|
157
|
-
|
|
137
|
+
##### Type parameters
|
|
138
|
+
|
|
139
|
+
| Name | Type |
|
|
140
|
+
| :------ | :------ |
|
|
141
|
+
| `T` | `never` |
|
|
142
|
+
| `R` | `any` |
|
|
143
|
+
|
|
144
|
+
##### Parameters
|
|
145
|
+
|
|
146
|
+
| Name | Type |
|
|
147
|
+
| :------ | :------ |
|
|
148
|
+
| `ms` | `number` |
|
|
149
|
+
| `reason` | `R` \| `PromiseLike`<`R`\> \| () => `R` \| `PromiseLike`<`R`\> |
|
|
150
|
+
|
|
151
|
+
##### Returns
|
|
152
|
+
|
|
153
|
+
`Promise`<`T`\>
|
|
154
|
+
|
|
155
|
+
___
|
|
156
|
+
|
|
157
|
+
#### delayedResolve
|
|
158
|
+
|
|
159
|
+
▸ **delayedResolve**<`T`\>(`ms`, `result?`): `Promise`<`T`\>
|
|
160
|
+
|
|
161
|
+
See [delayedResolve](#delayedresolve) for full documentation.
|
|
162
|
+
|
|
163
|
+
##### Type parameters
|
|
164
|
+
|
|
165
|
+
| Name |
|
|
166
|
+
| :------ |
|
|
167
|
+
| `T` |
|
|
168
|
+
|
|
169
|
+
##### Parameters
|
|
170
|
+
|
|
171
|
+
| Name | Type |
|
|
172
|
+
| :------ | :------ |
|
|
173
|
+
| `ms` | `number` |
|
|
174
|
+
| `result?` | `T` \| `PromiseLike`<`T`\> \| () => `T` \| `PromiseLike`<`T`\> |
|
|
175
|
+
|
|
176
|
+
##### Returns
|
|
177
|
+
|
|
178
|
+
`Promise`<`T`\>
|
|
179
|
+
|
|
180
|
+
___
|
|
181
|
+
|
|
182
|
+
#### inParallel
|
|
183
|
+
|
|
184
|
+
▸ **inParallel**<`Data`, `Result`, `TError`\>(`parallelism`, `jobs`, `operation`, `options?`): `Promise`<(`Result` \| `TError`)[]\>
|
|
185
|
+
|
|
186
|
+
See [inParallel](#inparallel) for full documentation.
|
|
187
|
+
|
|
188
|
+
##### Type parameters
|
|
189
|
+
|
|
190
|
+
| Name | Type |
|
|
191
|
+
| :------ | :------ |
|
|
192
|
+
| `Data` | `Data` |
|
|
193
|
+
| `Result` | `Result` |
|
|
194
|
+
| `TError` | `Result` |
|
|
195
|
+
|
|
196
|
+
##### Parameters
|
|
197
|
+
|
|
198
|
+
| Name | Type |
|
|
199
|
+
| :------ | :------ |
|
|
200
|
+
| `parallelism` | `number` |
|
|
201
|
+
| `jobs` | `Iterable`<`Data`\> |
|
|
202
|
+
| `operation` | (`job`: `Data`, `index`: `number`) => `Promise`<`Result`\> |
|
|
203
|
+
| `options?` | `Object` |
|
|
204
|
+
| `options.abortOnError` | `boolean` |
|
|
205
|
+
|
|
206
|
+
##### Returns
|
|
207
|
+
|
|
208
|
+
`Promise`<(`Result` \| `TError`)[]\>
|
|
209
|
+
|
|
210
|
+
___
|
|
211
|
+
|
|
212
|
+
#### promiseState
|
|
213
|
+
|
|
214
|
+
▸ **promiseState**(`p`): `Promise`<[`PromiseState`](#enumspromisestatemd)\>
|
|
215
|
+
|
|
216
|
+
See [promiseState](#promisestate) for full documentation.
|
|
217
|
+
|
|
218
|
+
##### Parameters
|
|
219
|
+
|
|
220
|
+
| Name | Type |
|
|
221
|
+
| :------ | :------ |
|
|
222
|
+
| `p` | `Promise`<`any`\> |
|
|
223
|
+
|
|
224
|
+
##### Returns
|
|
225
|
+
|
|
226
|
+
`Promise`<[`PromiseState`](#enumspromisestatemd)\>
|
|
227
|
+
|
|
228
|
+
___
|
|
229
|
+
|
|
230
|
+
#### repeat
|
|
231
|
+
|
|
232
|
+
▸ **repeat**<`Result`, `Param`, `Collection`\>(`operation`, `nextParameter`, `collect`, `initialCollection`, `initialParameter?`): `Promise`<`Collection`\>
|
|
233
|
+
|
|
234
|
+
See [repeat](#repeat) for full documentation.
|
|
235
|
+
|
|
236
|
+
##### Type parameters
|
|
237
|
+
|
|
238
|
+
| Name |
|
|
239
|
+
| :------ |
|
|
240
|
+
| `Result` |
|
|
241
|
+
| `Param` |
|
|
242
|
+
| `Collection` |
|
|
243
|
+
|
|
244
|
+
##### Parameters
|
|
245
|
+
|
|
246
|
+
| Name | Type |
|
|
247
|
+
| :------ | :------ |
|
|
248
|
+
| `operation` | (`parameter`: `Partial`<`Param`\>) => `Promise`<`Result`\> |
|
|
249
|
+
| `nextParameter` | (`response`: `Result`) => ``null`` \| `Partial`<`Param`\> \| `Promise`<`Partial`<`Param`\>\> |
|
|
250
|
+
| `collect` | (`collection`: `Collection`, `result`: `Result`) => `Collection` |
|
|
251
|
+
| `initialCollection` | `Collection` |
|
|
252
|
+
| `initialParameter` | `Partial`<`Param`\> |
|
|
253
|
+
|
|
254
|
+
##### Returns
|
|
255
|
+
|
|
256
|
+
`Promise`<`Collection`\>
|
|
257
|
+
|
|
258
|
+
___
|
|
259
|
+
|
|
260
|
+
#### synchronised
|
|
261
|
+
|
|
262
|
+
▸ **synchronised**<`T`\>(`lock`, `operation`): `Promise`<`T`\>
|
|
263
|
+
|
|
264
|
+
See [synchronised](#synchronised) for full documentation.
|
|
265
|
+
|
|
266
|
+
##### Type parameters
|
|
267
|
+
|
|
268
|
+
| Name |
|
|
269
|
+
| :------ |
|
|
270
|
+
| `T` |
|
|
271
|
+
|
|
272
|
+
##### Parameters
|
|
273
|
+
|
|
274
|
+
| Name | Type |
|
|
275
|
+
| :------ | :------ |
|
|
276
|
+
| `lock` | `unknown` |
|
|
277
|
+
| `operation` | (`previousState`: `undefined` \| [`PromiseState`](#enumspromisestatemd), `previousSettledState`: `undefined` \| [`PromiseState`](#enumspromisestatemd), `previousResult`: `any`) => `Promise`<`T`\> |
|
|
278
|
+
|
|
279
|
+
##### Returns
|
|
280
|
+
|
|
281
|
+
`Promise`<`T`\>
|
|
282
|
+
|
|
283
|
+
___
|
|
284
|
+
|
|
285
|
+
#### synchronized
|
|
286
|
+
|
|
287
|
+
▸ **synchronized**<`T`\>(`lock`, `operation`): `Promise`<`T`\>
|
|
288
|
+
|
|
289
|
+
See [synchronized](#synchronized) for full documentation.
|
|
290
|
+
|
|
291
|
+
##### Type parameters
|
|
292
|
+
|
|
293
|
+
| Name |
|
|
294
|
+
| :------ |
|
|
295
|
+
| `T` |
|
|
296
|
+
|
|
297
|
+
##### Parameters
|
|
298
|
+
|
|
299
|
+
| Name | Type |
|
|
300
|
+
| :------ | :------ |
|
|
301
|
+
| `lock` | `unknown` |
|
|
302
|
+
| `operation` | (`previousState`: `undefined` \| [`PromiseState`](#enumspromisestatemd), `previousSettledState`: `undefined` \| [`PromiseState`](#enumspromisestatemd), `previousResult`: `any`) => `Promise`<`T`\> |
|
|
303
|
+
|
|
304
|
+
##### Returns
|
|
305
|
+
|
|
306
|
+
`Promise`<`T`\>
|
|
307
|
+
|
|
308
|
+
___
|
|
309
|
+
|
|
310
|
+
#### timeoutReject
|
|
311
|
+
|
|
312
|
+
▸ **timeoutReject**<`T`, `R`\>(`operation`, `ms`, `rejectReason`): `Promise`<`T`\>
|
|
313
|
+
|
|
314
|
+
See [timeoutReject](#timeoutreject) for full documentation.
|
|
315
|
+
|
|
316
|
+
##### Type parameters
|
|
317
|
+
|
|
318
|
+
| Name | Type |
|
|
319
|
+
| :------ | :------ |
|
|
320
|
+
| `T` | `never` |
|
|
321
|
+
| `R` | `any` |
|
|
322
|
+
|
|
323
|
+
##### Parameters
|
|
324
|
+
|
|
325
|
+
| Name | Type |
|
|
326
|
+
| :------ | :------ |
|
|
327
|
+
| `operation` | `Promise`<`T`\> \| () => `Promise`<`T`\> |
|
|
328
|
+
| `ms` | `number` |
|
|
329
|
+
| `rejectReason` | `R` \| `PromiseLike`<`R`\> \| () => `R` \| `PromiseLike`<`R`\> |
|
|
330
|
+
|
|
331
|
+
##### Returns
|
|
332
|
+
|
|
333
|
+
`Promise`<`T`\>
|
|
334
|
+
|
|
335
|
+
___
|
|
336
|
+
|
|
337
|
+
#### timeoutResolve
|
|
338
|
+
|
|
339
|
+
▸ **timeoutResolve**<`T`\>(`operation`, `ms`, `result?`): `Promise`<`T`\>
|
|
340
|
+
|
|
341
|
+
See [timeoutResolve](#timeoutresolve) for full documentation.
|
|
342
|
+
|
|
343
|
+
##### Type parameters
|
|
344
|
+
|
|
345
|
+
| Name |
|
|
346
|
+
| :------ |
|
|
347
|
+
| `T` |
|
|
348
|
+
|
|
349
|
+
##### Parameters
|
|
350
|
+
|
|
351
|
+
| Name | Type |
|
|
352
|
+
| :------ | :------ |
|
|
353
|
+
| `operation` | `Promise`<`T`\> \| () => `Promise`<`T`\> |
|
|
354
|
+
| `ms` | `number` |
|
|
355
|
+
| `result?` | `T` \| `PromiseLike`<`T`\> \| () => `T` \| `PromiseLike`<`T`\> |
|
|
356
|
+
|
|
357
|
+
##### Returns
|
|
158
358
|
|
|
159
|
-
|
|
359
|
+
`Promise`<`T`\>
|
|
360
|
+
|
|
361
|
+
___
|
|
362
|
+
|
|
363
|
+
#### withRetry
|
|
364
|
+
|
|
365
|
+
▸ **withRetry**<`Result`, `TError`\>(`operation`, `backoff`, `shouldRetry?`): `Promise`<`Result`\>
|
|
366
|
+
|
|
367
|
+
See [withRetry](#withretry) for full documentation.
|
|
368
|
+
|
|
369
|
+
##### Type parameters
|
|
160
370
|
|
|
161
|
-
|
|
371
|
+
| Name | Type |
|
|
372
|
+
| :------ | :------ |
|
|
373
|
+
| `Result` | `Result` |
|
|
374
|
+
| `TError` | `any` |
|
|
162
375
|
|
|
163
|
-
|
|
376
|
+
##### Parameters
|
|
164
377
|
|
|
165
|
-
|
|
378
|
+
| Name | Type |
|
|
379
|
+
| :------ | :------ |
|
|
380
|
+
| `operation` | (`attempt`: `number`, `previousResult`: `undefined` \| `Result`, `previousError`: `undefined` \| `TError`) => `Promise`<`Result`\> |
|
|
381
|
+
| `backoff` | `number`[] \| (`attempt`: `number`, `previousResult`: `undefined` \| `Result`, `previousError`: `undefined` \| `TError`) => `undefined` \| `number` |
|
|
382
|
+
| `shouldRetry` | (`previousError`: `undefined` \| `TError`, `previousResult`: `undefined` \| `Result`, `attempt`: `number`) => `boolean` |
|
|
383
|
+
|
|
384
|
+
##### Returns
|
|
385
|
+
|
|
386
|
+
`Promise`<`Result`\>
|
|
166
387
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
- [synchronized](#synchronized)
|
|
174
|
-
- [timeoutReject](#timeoutreject)
|
|
175
|
-
- [timeoutResolve](#timeoutresolve)
|
|
176
|
-
- [withRetry](#withretry)
|
|
388
|
+
## Classes
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
<a name="classespromiseutilsmd"></a>
|
|
392
|
+
|
|
393
|
+
### Class: PromiseUtils
|
|
177
394
|
|
|
178
395
|
#### Constructors
|
|
179
396
|
|
|
@@ -228,7 +445,7 @@ Create a Promise that resolves after number of milliseconds specified
|
|
|
228
445
|
| Name | Type | Description |
|
|
229
446
|
| :------ | :------ | :------ |
|
|
230
447
|
| `ms` | `number` | number of milliseconds after which the created Promise would resolve |
|
|
231
|
-
| `result?` | `T` \| `PromiseLike`<`T`\> \| () => `T` \| `PromiseLike`<`T`\> | the result to be resolved for the Promise, or a function that supplies the
|
|
448
|
+
| `result?` | `T` \| `PromiseLike`<`T`\> \| () => `T` \| `PromiseLike`<`T`\> | the result to be resolved for the Promise, or a function that supplies the result. |
|
|
232
449
|
|
|
233
450
|
###### Returns
|
|
234
451
|
|
|
@@ -240,23 +457,17 @@ ___
|
|
|
240
457
|
|
|
241
458
|
##### inParallel
|
|
242
459
|
|
|
243
|
-
▸ `Static` **inParallel**<`Data`, `Result`, `TError`\>(`parallelism`, `jobs`, `operation`): `Promise`<(`Result` \| `TError`)[]\>
|
|
460
|
+
▸ `Static` **inParallel**<`Data`, `Result`, `TError`\>(`parallelism`, `jobs`, `operation`, `options?`): `Promise`<(`Result` \| `TError`)[]\>
|
|
244
461
|
|
|
245
462
|
Run multiple jobs/operations in parallel.
|
|
246
463
|
|
|
247
|
-
|
|
248
|
-
|
|
464
|
+
By default this function does not throw / reject with error when any of the job/operation fails.
|
|
465
|
+
Operation errors are returned together with operation results in the same returned array.
|
|
466
|
+
That also means this function only returns when all the jobs/operations settle (either resolve or reject).
|
|
249
467
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
const topicAttributes = (await sns.getTopicAttributes({ TopicArn: topicArn }).promise()).Attributes!;
|
|
253
|
-
const topicDetails = { ...topicAttributes, subscriptions: [] } as any;
|
|
254
|
-
if (this.shouldInclude(topicArn)) {
|
|
255
|
-
inventory.snsTopicsByArn.set(topicArn, topicDetails);
|
|
256
|
-
}
|
|
257
|
-
});
|
|
468
|
+
However, if options.abortOnError is true, this function throws / rejects with error when any of the job/operation fails.
|
|
469
|
+
That also means, some of the jobs/operations may not get the chance to be executed if one of them fails.
|
|
258
470
|
|
|
259
|
-
```
|
|
260
471
|
###### Type parameters
|
|
261
472
|
|
|
262
473
|
| Name | Type | Description |
|
|
@@ -270,16 +481,34 @@ await PromiseUtils.inParallel(5, topicArns, async topicArn => {
|
|
|
270
481
|
| Name | Type | Description |
|
|
271
482
|
| :------ | :------ | :------ |
|
|
272
483
|
| `parallelism` | `number` | how many jobs/operations can be running at the same time |
|
|
273
|
-
| `jobs` | `Iterable`<`Data`\> | job data which will be the input to operation function.
|
|
484
|
+
| `jobs` | `Iterable`<`Data`\> | job data which will be the input to operation function. This function is safe when there are infinite unknown number of elements in the job data. |
|
|
274
485
|
| `operation` | (`job`: `Data`, `index`: `number`) => `Promise`<`Result`\> | the function that turns job data into result asynchronously |
|
|
486
|
+
| `options?` | `Object` | Options for controlling the behavior of this function. |
|
|
487
|
+
| `options.abortOnError` | `boolean` | - |
|
|
275
488
|
|
|
276
489
|
###### Returns
|
|
277
490
|
|
|
278
491
|
`Promise`<(`Result` \| `TError`)[]\>
|
|
279
492
|
|
|
280
493
|
Promise of void if the operation function does not return a value,
|
|
281
|
-
or promise of an array containing
|
|
282
|
-
In the array containing
|
|
494
|
+
or promise of an array containing outcomes from the operation function.
|
|
495
|
+
In the returned array containing outcomes, each element is either the fulfilled result, or the rejected error/reason.
|
|
496
|
+
|
|
497
|
+
**`Example`**
|
|
498
|
+
|
|
499
|
+
```ts
|
|
500
|
+
const attributesAndPossibleErrors = await PromiseUtils.inParallel(5, topicArns, async (topicArn) => {
|
|
501
|
+
const topicAttributes = (await sns.getTopicAttributes({ TopicArn: topicArn }).promise()).Attributes!;
|
|
502
|
+
return topicAttributes;
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
let results: Array<JobResult>;
|
|
506
|
+
try {
|
|
507
|
+
results = await PromiseUtils.inParallel(100, jobs, async (job) => processor.process(job), { abortOnError: true });
|
|
508
|
+
} catch (error) {
|
|
509
|
+
// handle the error
|
|
510
|
+
}
|
|
511
|
+
```
|
|
283
512
|
|
|
284
513
|
___
|
|
285
514
|
|
|
@@ -300,7 +529,7 @@ Please note that the returned value is a Promise, although it resolves immediate
|
|
|
300
529
|
|
|
301
530
|
`Promise`<[`PromiseState`](#enumspromisestatemd)\>
|
|
302
531
|
|
|
303
|
-
A Promise that resolves immediately
|
|
532
|
+
A Promise that resolves immediately containing the state of the input Promise
|
|
304
533
|
|
|
305
534
|
___
|
|
306
535
|
|
|
@@ -311,17 +540,6 @@ ___
|
|
|
311
540
|
Do an operation repeatedly and collect all the results.
|
|
312
541
|
This function is useful for client side pagination.
|
|
313
542
|
|
|
314
|
-
**`example`**
|
|
315
|
-
```javascript
|
|
316
|
-
|
|
317
|
-
const domainNameObjects = await PromiseUtils.repeat(
|
|
318
|
-
pagingParam => apig.getDomainNames({limit: 500, ...pagingParam}).promise(),
|
|
319
|
-
esponse => response.position? {position: response.position} : null,
|
|
320
|
-
(collection, response) => collection.concat(response.items!),
|
|
321
|
-
[] as APIGateway.DomainName[],
|
|
322
|
-
);
|
|
323
|
-
|
|
324
|
-
```
|
|
325
543
|
###### Type parameters
|
|
326
544
|
|
|
327
545
|
| Name | Description |
|
|
@@ -335,7 +553,7 @@ const domainNameObjects = await PromiseUtils.repeat(
|
|
|
335
553
|
| Name | Type | Description |
|
|
336
554
|
| :------ | :------ | :------ |
|
|
337
555
|
| `operation` | (`parameter`: `Partial`<`Param`\>) => `Promise`<`Result`\> | a function that takes paging parameter as input and outputs a result, normally the operation supports paging |
|
|
338
|
-
| `nextParameter` | (`response`: `Result`) => ``null`` \| `Partial`<`Param`\> \| `Promise`<`Partial`<`Param`\>\> | The function for calculating next parameter from the operation result.
|
|
556
|
+
| `nextParameter` | (`response`: `Result`) => ``null`` \| `Partial`<`Param`\> \| `Promise`<`Partial`<`Param`\>\> | The function for calculating next parameter from the operation result. Normally the parameter controls paging, This function should return null when next invocation of the operation function is not desired. If next invocation is desired, the return value of this function can be a Promise or not a Promise. |
|
|
339
557
|
| `collect` | (`collection`: `Collection`, `result`: `Result`) => `Collection` | the function for merging operation result into the collection |
|
|
340
558
|
| `initialCollection` | `Collection` | initial collection which would be the first argument passed into the first invocation of the collect function |
|
|
341
559
|
| `initialParameter` | `Partial`<`Param`\> | the parameter for the first operation |
|
|
@@ -346,13 +564,24 @@ const domainNameObjects = await PromiseUtils.repeat(
|
|
|
346
564
|
|
|
347
565
|
Promise of collection of all the results returned by the operation function
|
|
348
566
|
|
|
567
|
+
**`Example`**
|
|
568
|
+
|
|
569
|
+
```ts
|
|
570
|
+
const domainNameObjects = await PromiseUtils.repeat(
|
|
571
|
+
pagingParam => apig.getDomainNames({limit: 500, ...pagingParam}).promise(),
|
|
572
|
+
response => response.position? {position: response.position} : null,
|
|
573
|
+
(collection, response) => collection.concat(response.items!),
|
|
574
|
+
[] as APIGateway.DomainName[],
|
|
575
|
+
);
|
|
576
|
+
```
|
|
577
|
+
|
|
349
578
|
___
|
|
350
579
|
|
|
351
580
|
##### synchronised
|
|
352
581
|
|
|
353
582
|
▸ `Static` **synchronised**<`T`\>(`lock`, `operation`): `Promise`<`T`\>
|
|
354
583
|
|
|
355
|
-
This is just another spelling of [
|
|
584
|
+
This is just another spelling of [synchronized](#synchronized).
|
|
356
585
|
|
|
357
586
|
###### Type parameters
|
|
358
587
|
|
|
@@ -410,11 +639,11 @@ ___
|
|
|
410
639
|
|
|
411
640
|
▸ `Static` **timeoutReject**<`T`, `R`\>(`operation`, `ms`, `rejectReason`): `Promise`<`T`\>
|
|
412
641
|
|
|
413
|
-
|
|
414
|
-
If timeout
|
|
415
|
-
If timeout
|
|
416
|
-
|
|
417
|
-
|
|
642
|
+
Applies a timeout to a Promise or a function that returns a Promise.
|
|
643
|
+
If the timeout occurs, rejects with the specified reason.
|
|
644
|
+
If the timeout doesn't occur, the resolved result or rejection reason of the original Promise will be the outcome of the Promise returned from this function.
|
|
645
|
+
If the 'reason' parameter is a function and timeout doesn't occur, the function won't be called.
|
|
646
|
+
The rejection of the 'operation' parameter is not handled by this function, you may want to handle it outside of this function to avoid warnings like "(node:4330) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously".
|
|
418
647
|
|
|
419
648
|
###### Type parameters
|
|
420
649
|
|
|
@@ -427,15 +656,15 @@ just for avoiding warnings like "(node:4330) PromiseRejectionHandledWarning: Pro
|
|
|
427
656
|
|
|
428
657
|
| Name | Type | Description |
|
|
429
658
|
| :------ | :------ | :------ |
|
|
430
|
-
| `operation` | `Promise`<`T`\> |
|
|
431
|
-
| `ms` | `number` | number of milliseconds for the timeout |
|
|
432
|
-
| `rejectReason` | `R` \| `PromiseLike`<`R`\> \| () => `R` \| `PromiseLike`<`R`\> |
|
|
659
|
+
| `operation` | `Promise`<`T`\> \| () => `Promise`<`T`\> | The original Promise or a function that returns a Promise for which the timeout will be applied. |
|
|
660
|
+
| `ms` | `number` | The number of milliseconds for the timeout. |
|
|
661
|
+
| `rejectReason` | `R` \| `PromiseLike`<`R`\> \| () => `R` \| `PromiseLike`<`R`\> | The reason to reject with if the timeout occurs, or a function that supplies the reason. |
|
|
433
662
|
|
|
434
663
|
###### Returns
|
|
435
664
|
|
|
436
665
|
`Promise`<`T`\>
|
|
437
666
|
|
|
438
|
-
|
|
667
|
+
A new Promise that rejects with the specified reason if the timeout occurs.
|
|
439
668
|
|
|
440
669
|
___
|
|
441
670
|
|
|
@@ -443,11 +672,11 @@ ___
|
|
|
443
672
|
|
|
444
673
|
▸ `Static` **timeoutResolve**<`T`\>(`operation`, `ms`, `result?`): `Promise`<`T`\>
|
|
445
674
|
|
|
446
|
-
|
|
447
|
-
If timeout
|
|
448
|
-
If timeout
|
|
449
|
-
|
|
450
|
-
|
|
675
|
+
Applies a timeout to a Promise or a function that returns a Promise.
|
|
676
|
+
If the timeout occurs, resolves to the specified result.
|
|
677
|
+
If the timeout doesn't occur, the resolved result or rejection reason of the original Promise will be the outcome of the Promise returned from this function.
|
|
678
|
+
If the 'result' parameter is a function and timeout doesn't occur, the function won't be called.
|
|
679
|
+
The rejection of the 'operation' parameter is not handled by this function, you may want to handle it outside of this function to avoid warnings like "(node:4330) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously".
|
|
451
680
|
|
|
452
681
|
###### Type parameters
|
|
453
682
|
|
|
@@ -459,15 +688,15 @@ just for avoiding warnings like "(node:4330) PromiseRejectionHandledWarning: Pro
|
|
|
459
688
|
|
|
460
689
|
| Name | Type | Description |
|
|
461
690
|
| :------ | :------ | :------ |
|
|
462
|
-
| `operation` | `Promise`<`T`\> |
|
|
463
|
-
| `ms` | `number` | number of milliseconds for the timeout |
|
|
464
|
-
| `result?` | `T` \| `PromiseLike`<`T`\> \| () => `T` \| `PromiseLike`<`T`\> |
|
|
691
|
+
| `operation` | `Promise`<`T`\> \| () => `Promise`<`T`\> | The original Promise or a function that returns a Promise for which the timeout will be applied. |
|
|
692
|
+
| `ms` | `number` | The number of milliseconds for the timeout. |
|
|
693
|
+
| `result?` | `T` \| `PromiseLike`<`T`\> \| () => `T` \| `PromiseLike`<`T`\> | The result to be resolved with if the timeout occurs, or a function that supplies the result. |
|
|
465
694
|
|
|
466
695
|
###### Returns
|
|
467
696
|
|
|
468
697
|
`Promise`<`T`\>
|
|
469
698
|
|
|
470
|
-
|
|
699
|
+
A new Promise that resolves to the specified result if the timeout occurs.
|
|
471
700
|
|
|
472
701
|
___
|
|
473
702
|
|
|
@@ -477,14 +706,6 @@ ___
|
|
|
477
706
|
|
|
478
707
|
Do an operation repeatedly until a criteria is met.
|
|
479
708
|
|
|
480
|
-
**`example`**
|
|
481
|
-
```javascript
|
|
482
|
-
|
|
483
|
-
const result = await PromiseUtils.withRetry(() => doSomething(), [100, 200, 300, 500, 800, 1000]);
|
|
484
|
-
const result2 = await PromiseUtils.withRetry(() => doSomething(), Array.from({length: 10}, (_v, i) => 1000 * Math.min(FIBONACCI_SEQUENCE[i], 10), err => err.statusCode === 429);
|
|
485
|
-
const result3 = await PromiseUtils.withRetry(() => doSomething(), attempt => attempt <= 8 ? 1000 * Math.min(FIBONACCI_SEQUENCE[attempt - 1], 10) : undefined, err => err.statusCode === 429);
|
|
486
|
-
|
|
487
|
-
```
|
|
488
709
|
###### Type parameters
|
|
489
710
|
|
|
490
711
|
| Name | Type | Description |
|
|
@@ -497,8 +718,8 @@ const result3 = await PromiseUtils.withRetry(() => doSomething(), attempt => att
|
|
|
497
718
|
| Name | Type | Description |
|
|
498
719
|
| :------ | :------ | :------ |
|
|
499
720
|
| `operation` | (`attempt`: `number`, `previousResult`: `undefined` \| `Result`, `previousError`: `undefined` \| `TError`) => `Promise`<`Result`\> | a function that outputs a Promise result, normally the operation does not use its arguments |
|
|
500
|
-
| `backoff` | `number`[] \| (`attempt`: `number`, `previousResult`: `undefined` \| `Result`, `previousError`: `undefined` \| `TError`) => `undefined` \| `number` | Array of retry backoff periods (unit: milliseconds) or function for calculating them.
|
|
501
|
-
| `shouldRetry` | (`previousError`: `undefined` \| `TError`, `previousResult`: `undefined` \| `Result`, `attempt`: `number`) => `boolean` | Predicate function for deciding whether another call to the operation should happen.
|
|
721
|
+
| `backoff` | `number`[] \| (`attempt`: `number`, `previousResult`: `undefined` \| `Result`, `previousError`: `undefined` \| `TError`) => `undefined` \| `number` | Array of retry backoff periods (unit: milliseconds) or function for calculating them. If retry is desired, before making next call to the operation the desired backoff period would be waited. If the array runs out of elements or the function returns `undefined` or either the array or the function returns a negative number, there would be no further call to the operation. The `attempt` argument passed into backoff function starts from 1 because the function is called right after the first attempt and before the first retry. |
|
|
722
|
+
| `shouldRetry` | (`previousError`: `undefined` \| `TError`, `previousResult`: `undefined` \| `Result`, `attempt`: `number`) => `boolean` | Predicate function for deciding whether another call to the operation should happen. If this argument is not defined, retry would happen whenever the operation rejects with an error. `shouldRetry` would be evaluated before `backoff`. The `attempt` argument passed into shouldRetry function starts from 1. |
|
|
502
723
|
|
|
503
724
|
###### Returns
|
|
504
725
|
|
|
@@ -506,40 +727,38 @@ const result3 = await PromiseUtils.withRetry(() => doSomething(), attempt => att
|
|
|
506
727
|
|
|
507
728
|
Promise of the operation result potentially with retries already applied
|
|
508
729
|
|
|
730
|
+
**`Example`**
|
|
731
|
+
|
|
732
|
+
```ts
|
|
733
|
+
const result = await PromiseUtils.withRetry(() => doSomething(), [100, 200, 300, 500, 800, 1000]);
|
|
734
|
+
const result2 = await PromiseUtils.withRetry(() => doSomething(), Array.from({length: 10}, (_v, i) => 1000 * Math.min(FIBONACCI_SEQUENCE[i], 10), err => err.statusCode === 429);
|
|
735
|
+
const result3 = await PromiseUtils.withRetry(() => doSomething(), attempt => attempt <= 8 ? 1000 * Math.min(FIBONACCI_SEQUENCE[attempt - 1], 10) : undefined, err => err.statusCode === 429);
|
|
736
|
+
```
|
|
737
|
+
|
|
509
738
|
## Enums
|
|
510
739
|
|
|
511
740
|
|
|
512
741
|
<a name="enumspromisestatemd"></a>
|
|
513
742
|
|
|
514
|
-
[@handy-common-utils/promise-utils](#readmemd) / PromiseState
|
|
515
|
-
|
|
516
743
|
### Enumeration: PromiseState
|
|
517
744
|
|
|
518
745
|
The state of a Promise can only be one of: Pending, Fulfilled, and Rejected.
|
|
519
746
|
|
|
520
|
-
####
|
|
521
|
-
|
|
522
|
-
##### Enumeration members
|
|
523
|
-
|
|
524
|
-
- [Fulfilled](#fulfilled)
|
|
525
|
-
- [Pending](#pending)
|
|
526
|
-
- [Rejected](#rejected)
|
|
527
|
-
|
|
528
|
-
#### Enumeration members
|
|
747
|
+
#### Enumeration Members
|
|
529
748
|
|
|
530
749
|
##### Fulfilled
|
|
531
750
|
|
|
532
|
-
• **Fulfilled** =
|
|
751
|
+
• **Fulfilled** = ``"Fulfilled"``
|
|
533
752
|
|
|
534
753
|
___
|
|
535
754
|
|
|
536
755
|
##### Pending
|
|
537
756
|
|
|
538
|
-
• **Pending** =
|
|
757
|
+
• **Pending** = ``"Pending"``
|
|
539
758
|
|
|
540
759
|
___
|
|
541
760
|
|
|
542
761
|
##### Rejected
|
|
543
762
|
|
|
544
|
-
• **Rejected** =
|
|
763
|
+
• **Rejected** = ``"Rejected"``
|
|
545
764
|
<!-- API end -->
|
package/dist/promise-utils.d.ts
CHANGED
|
@@ -38,7 +38,7 @@ export declare abstract class PromiseUtils {
|
|
|
38
38
|
* @example
|
|
39
39
|
* const domainNameObjects = await PromiseUtils.repeat(
|
|
40
40
|
* pagingParam => apig.getDomainNames({limit: 500, ...pagingParam}).promise(),
|
|
41
|
-
*
|
|
41
|
+
* response => response.position? {position: response.position} : null,
|
|
42
42
|
* (collection, response) => collection.concat(response.items!),
|
|
43
43
|
* [] as APIGateway.DomainName[],
|
|
44
44
|
* );
|
|
@@ -86,16 +86,26 @@ export declare abstract class PromiseUtils {
|
|
|
86
86
|
/**
|
|
87
87
|
* Run multiple jobs/operations in parallel.
|
|
88
88
|
*
|
|
89
|
+
* By default this function does not throw / reject with error when any of the job/operation fails.
|
|
90
|
+
* Operation errors are returned together with operation results in the same returned array.
|
|
91
|
+
* That also means this function only returns when all the jobs/operations settle (either resolve or reject).
|
|
92
|
+
*
|
|
93
|
+
* However, if options.abortOnError is true, this function throws / rejects with error when any of the job/operation fails.
|
|
94
|
+
* That also means, some of the jobs/operations may not get the chance to be executed if one of them fails.
|
|
95
|
+
*
|
|
89
96
|
* @example
|
|
90
|
-
* const
|
|
91
|
-
* await PromiseUtils.inParallel(5, topicArns, async topicArn => {
|
|
97
|
+
* const attributesAndPossibleErrors = await PromiseUtils.inParallel(5, topicArns, async (topicArn) => {
|
|
92
98
|
* const topicAttributes = (await sns.getTopicAttributes({ TopicArn: topicArn }).promise()).Attributes!;
|
|
93
|
-
*
|
|
94
|
-
* if (this.shouldInclude(topicArn)) {
|
|
95
|
-
* inventory.snsTopicsByArn.set(topicArn, topicDetails);
|
|
96
|
-
* }
|
|
99
|
+
* return topicAttributes;
|
|
97
100
|
* });
|
|
98
101
|
*
|
|
102
|
+
* let results: Array<JobResult>;
|
|
103
|
+
* try {
|
|
104
|
+
* results = await PromiseUtils.inParallel(100, jobs, async (job) => processor.process(job), { abortOnError: true });
|
|
105
|
+
* } catch (error) {
|
|
106
|
+
* // handle the error
|
|
107
|
+
* }
|
|
108
|
+
*
|
|
99
109
|
* @template Data Type of the job data, usually it would be an Array
|
|
100
110
|
* @template Result Type of the return value of the operation function
|
|
101
111
|
*
|
|
@@ -103,15 +113,18 @@ export declare abstract class PromiseUtils {
|
|
|
103
113
|
* @param jobs job data which will be the input to operation function.
|
|
104
114
|
* This function is safe when there are infinite unknown number of elements in the job data.
|
|
105
115
|
* @param operation the function that turns job data into result asynchronously
|
|
116
|
+
* @param options Options for controlling the behavior of this function.
|
|
106
117
|
* @returns Promise of void if the operation function does not return a value,
|
|
107
|
-
* or promise of an array containing
|
|
108
|
-
* In the array containing
|
|
118
|
+
* or promise of an array containing outcomes from the operation function.
|
|
119
|
+
* In the returned array containing outcomes, each element is either the fulfilled result, or the rejected error/reason.
|
|
109
120
|
*/
|
|
110
|
-
static inParallel<Data, Result, TError = Result>(parallelism: number, jobs: Iterable<Data>, operation: (job: Data, index: number) => Promise<Result
|
|
121
|
+
static inParallel<Data, Result, TError = Result>(parallelism: number, jobs: Iterable<Data>, operation: (job: Data, index: number) => Promise<Result>, options?: {
|
|
122
|
+
abortOnError: boolean;
|
|
123
|
+
}): Promise<Array<Result | TError>>;
|
|
111
124
|
/**
|
|
112
125
|
* Create a Promise that resolves after number of milliseconds specified
|
|
113
126
|
* @param ms number of milliseconds after which the created Promise would resolve
|
|
114
|
-
* @param result the result to be resolved for the Promise, or a function that supplies the
|
|
127
|
+
* @param result the result to be resolved for the Promise, or a function that supplies the result.
|
|
115
128
|
* @returns the new Promise created
|
|
116
129
|
*/
|
|
117
130
|
static delayedResolve<T>(ms: number, result?: T | PromiseLike<T> | (() => (T | PromiseLike<T>))): Promise<T>;
|
|
@@ -124,34 +137,36 @@ export declare abstract class PromiseUtils {
|
|
|
124
137
|
*/
|
|
125
138
|
static delayedReject<T = never, R = any>(ms: number, reason: R | PromiseLike<R> | (() => R | PromiseLike<R>)): Promise<T>;
|
|
126
139
|
/**
|
|
127
|
-
*
|
|
128
|
-
* If timeout
|
|
129
|
-
* If timeout
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* @param
|
|
134
|
-
* @param
|
|
135
|
-
* @
|
|
140
|
+
* Applies a timeout to a Promise or a function that returns a Promise.
|
|
141
|
+
* If the timeout occurs, resolves to the specified result.
|
|
142
|
+
* If the timeout doesn't occur, the resolved result or rejection reason of the original Promise will be the outcome of the Promise returned from this function.
|
|
143
|
+
* If the 'result' parameter is a function and timeout doesn't occur, the function won't be called.
|
|
144
|
+
* The rejection of the 'operation' parameter is not handled by this function, you may want to handle it outside of this function to avoid warnings like "(node:4330) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously".
|
|
145
|
+
*
|
|
146
|
+
* @param operation The original Promise or a function that returns a Promise for which the timeout will be applied.
|
|
147
|
+
* @param ms The number of milliseconds for the timeout.
|
|
148
|
+
* @param result The result to be resolved with if the timeout occurs, or a function that supplies the result.
|
|
149
|
+
* @return A new Promise that resolves to the specified result if the timeout occurs.
|
|
136
150
|
*/
|
|
137
|
-
static timeoutResolve<T>(operation: Promise<T
|
|
151
|
+
static timeoutResolve<T>(operation: Promise<T> | (() => Promise<T>), ms: number, result?: T | PromiseLike<T> | (() => (T | PromiseLike<T>)) | undefined): Promise<T>;
|
|
138
152
|
/**
|
|
139
|
-
*
|
|
140
|
-
* If timeout
|
|
141
|
-
* If timeout
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
*
|
|
145
|
-
* @param
|
|
146
|
-
* @param
|
|
147
|
-
* @
|
|
153
|
+
* Applies a timeout to a Promise or a function that returns a Promise.
|
|
154
|
+
* If the timeout occurs, rejects with the specified reason.
|
|
155
|
+
* If the timeout doesn't occur, the resolved result or rejection reason of the original Promise will be the outcome of the Promise returned from this function.
|
|
156
|
+
* If the 'reason' parameter is a function and timeout doesn't occur, the function won't be called.
|
|
157
|
+
* The rejection of the 'operation' parameter is not handled by this function, you may want to handle it outside of this function to avoid warnings like "(node:4330) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously".
|
|
158
|
+
*
|
|
159
|
+
* @param operation The original Promise or a function that returns a Promise for which the timeout will be applied.
|
|
160
|
+
* @param ms The number of milliseconds for the timeout.
|
|
161
|
+
* @param rejectReason The reason to reject with if the timeout occurs, or a function that supplies the reason.
|
|
162
|
+
* @return A new Promise that rejects with the specified reason if the timeout occurs.
|
|
148
163
|
*/
|
|
149
|
-
static timeoutReject<T = never, R = any>(operation: Promise<T
|
|
164
|
+
static timeoutReject<T = never, R = any>(operation: Promise<T> | (() => Promise<T>), ms: number, rejectReason: R | PromiseLike<R> | (() => R | PromiseLike<R>)): Promise<T>;
|
|
150
165
|
/**
|
|
151
166
|
* Get the state of the Promise.
|
|
152
167
|
* Please note that the returned value is a Promise, although it resolves immediately.
|
|
153
168
|
* @param p the Promise for which we would like to know its state
|
|
154
|
-
* @return A Promise that resolves immediately
|
|
169
|
+
* @return A Promise that resolves immediately containing the state of the input Promise
|
|
155
170
|
*/
|
|
156
171
|
static promiseState(p: Promise<any>): Promise<PromiseState>;
|
|
157
172
|
private static synchronizationLocks;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"promise-utils.d.ts","sourceRoot":"","sources":["../src/promise-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,UAAkJ,CAAC;AAElL;;;;;;;;;;GAUG;AACH,eAAO,MAAM,oBAAoB,UAA6K,CAAC;AAE/M;;GAEG;AACH,oBAAY,YAAY;IACtB,OAAO,YAAY;IACnB,SAAS,cAAc;IACvB,QAAQ,aAAa;CACtB;AAED,8BAAsB,YAAY;IAChC;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;WACU,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,EAC3C,SAAS,EAAE,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,EACzD,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,IAAI,EACpF,OAAO,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,KAAK,UAAU,EAC/D,iBAAiB,EAAE,UAAU,EAC7B,gBAAgB,GAAE,OAAO,CAAC,KAAK,CAAM,GACpC,OAAO,CAAC,UAAU,CAAC;IAetB;;;;;;;;;;;;;;;;;;;;;;OAsBG;WACU,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,GAAG,EACzC,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAC,SAAS,EAAE,aAAa,EAAE,MAAM,GAAC,SAAS,KAAK,OAAO,CAAC,MAAM,CAAC,EAClH,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAC,SAAS,EAAE,aAAa,EAAE,MAAM,GAAC,SAAS,KAAK,MAAM,GAAC,SAAS,CAAC,EACnI,WAAW,GAAE,CAAC,aAAa,EAAE,MAAM,GAAC,SAAS,EAAE,cAAc,EAAE,MAAM,GAAC,SAAS,EAAE,OAAO,EAAE,MAAM,KAAK,OAAmF,GACvL,OAAO,CAAC,MAAM,CAAC;IAyBlB
|
|
1
|
+
{"version":3,"file":"promise-utils.d.ts","sourceRoot":"","sources":["../src/promise-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/promise-utils.js
CHANGED
|
@@ -33,7 +33,7 @@ var PromiseState;
|
|
|
33
33
|
PromiseState["Pending"] = "Pending";
|
|
34
34
|
PromiseState["Fulfilled"] = "Fulfilled";
|
|
35
35
|
PromiseState["Rejected"] = "Rejected";
|
|
36
|
-
})(PromiseState
|
|
36
|
+
})(PromiseState || (exports.PromiseState = PromiseState = {}));
|
|
37
37
|
class PromiseUtils {
|
|
38
38
|
/**
|
|
39
39
|
* Do an operation repeatedly and collect all the results.
|
|
@@ -42,7 +42,7 @@ class PromiseUtils {
|
|
|
42
42
|
* @example
|
|
43
43
|
* const domainNameObjects = await PromiseUtils.repeat(
|
|
44
44
|
* pagingParam => apig.getDomainNames({limit: 500, ...pagingParam}).promise(),
|
|
45
|
-
*
|
|
45
|
+
* response => response.position? {position: response.position} : null,
|
|
46
46
|
* (collection, response) => collection.concat(response.items!),
|
|
47
47
|
* [] as APIGateway.DomainName[],
|
|
48
48
|
* );
|
|
@@ -120,16 +120,26 @@ class PromiseUtils {
|
|
|
120
120
|
/**
|
|
121
121
|
* Run multiple jobs/operations in parallel.
|
|
122
122
|
*
|
|
123
|
+
* By default this function does not throw / reject with error when any of the job/operation fails.
|
|
124
|
+
* Operation errors are returned together with operation results in the same returned array.
|
|
125
|
+
* That also means this function only returns when all the jobs/operations settle (either resolve or reject).
|
|
126
|
+
*
|
|
127
|
+
* However, if options.abortOnError is true, this function throws / rejects with error when any of the job/operation fails.
|
|
128
|
+
* That also means, some of the jobs/operations may not get the chance to be executed if one of them fails.
|
|
129
|
+
*
|
|
123
130
|
* @example
|
|
124
|
-
* const
|
|
125
|
-
* await PromiseUtils.inParallel(5, topicArns, async topicArn => {
|
|
131
|
+
* const attributesAndPossibleErrors = await PromiseUtils.inParallel(5, topicArns, async (topicArn) => {
|
|
126
132
|
* const topicAttributes = (await sns.getTopicAttributes({ TopicArn: topicArn }).promise()).Attributes!;
|
|
127
|
-
*
|
|
128
|
-
* if (this.shouldInclude(topicArn)) {
|
|
129
|
-
* inventory.snsTopicsByArn.set(topicArn, topicDetails);
|
|
130
|
-
* }
|
|
133
|
+
* return topicAttributes;
|
|
131
134
|
* });
|
|
132
135
|
*
|
|
136
|
+
* let results: Array<JobResult>;
|
|
137
|
+
* try {
|
|
138
|
+
* results = await PromiseUtils.inParallel(100, jobs, async (job) => processor.process(job), { abortOnError: true });
|
|
139
|
+
* } catch (error) {
|
|
140
|
+
* // handle the error
|
|
141
|
+
* }
|
|
142
|
+
*
|
|
133
143
|
* @template Data Type of the job data, usually it would be an Array
|
|
134
144
|
* @template Result Type of the return value of the operation function
|
|
135
145
|
*
|
|
@@ -137,11 +147,12 @@ class PromiseUtils {
|
|
|
137
147
|
* @param jobs job data which will be the input to operation function.
|
|
138
148
|
* This function is safe when there are infinite unknown number of elements in the job data.
|
|
139
149
|
* @param operation the function that turns job data into result asynchronously
|
|
150
|
+
* @param options Options for controlling the behavior of this function.
|
|
140
151
|
* @returns Promise of void if the operation function does not return a value,
|
|
141
|
-
* or promise of an array containing
|
|
142
|
-
* In the array containing
|
|
152
|
+
* or promise of an array containing outcomes from the operation function.
|
|
153
|
+
* In the returned array containing outcomes, each element is either the fulfilled result, or the rejected error/reason.
|
|
143
154
|
*/
|
|
144
|
-
static async inParallel(parallelism, jobs, operation) {
|
|
155
|
+
static async inParallel(parallelism, jobs, operation, options) {
|
|
145
156
|
if (parallelism < 1) {
|
|
146
157
|
parallelism = 1;
|
|
147
158
|
}
|
|
@@ -158,7 +169,7 @@ class PromiseUtils {
|
|
|
158
169
|
const job = iteratorResult.value;
|
|
159
170
|
const jobIndex = index++;
|
|
160
171
|
const jobResultPromise = operation(job, jobIndex);
|
|
161
|
-
jobResults[jobIndex] = await jobResultPromise.catch(error => error);
|
|
172
|
+
jobResults[jobIndex] = (options === null || options === void 0 ? void 0 : options.abortOnError) ? await jobResultPromise : await jobResultPromise.catch(error => error);
|
|
162
173
|
}
|
|
163
174
|
});
|
|
164
175
|
await Promise.all(promises);
|
|
@@ -167,7 +178,7 @@ class PromiseUtils {
|
|
|
167
178
|
/**
|
|
168
179
|
* Create a Promise that resolves after number of milliseconds specified
|
|
169
180
|
* @param ms number of milliseconds after which the created Promise would resolve
|
|
170
|
-
* @param result the result to be resolved for the Promise, or a function that supplies the
|
|
181
|
+
* @param result the result to be resolved for the Promise, or a function that supplies the result.
|
|
171
182
|
* @returns the new Promise created
|
|
172
183
|
*/
|
|
173
184
|
static delayedResolve(ms, result) {
|
|
@@ -189,40 +200,44 @@ class PromiseUtils {
|
|
|
189
200
|
}, ms));
|
|
190
201
|
}
|
|
191
202
|
/**
|
|
192
|
-
*
|
|
193
|
-
* If timeout
|
|
194
|
-
* If timeout
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
* @param
|
|
199
|
-
* @param
|
|
200
|
-
* @
|
|
203
|
+
* Applies a timeout to a Promise or a function that returns a Promise.
|
|
204
|
+
* If the timeout occurs, resolves to the specified result.
|
|
205
|
+
* If the timeout doesn't occur, the resolved result or rejection reason of the original Promise will be the outcome of the Promise returned from this function.
|
|
206
|
+
* If the 'result' parameter is a function and timeout doesn't occur, the function won't be called.
|
|
207
|
+
* The rejection of the 'operation' parameter is not handled by this function, you may want to handle it outside of this function to avoid warnings like "(node:4330) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously".
|
|
208
|
+
*
|
|
209
|
+
* @param operation The original Promise or a function that returns a Promise for which the timeout will be applied.
|
|
210
|
+
* @param ms The number of milliseconds for the timeout.
|
|
211
|
+
* @param result The result to be resolved with if the timeout occurs, or a function that supplies the result.
|
|
212
|
+
* @return A new Promise that resolves to the specified result if the timeout occurs.
|
|
201
213
|
*/
|
|
202
214
|
static timeoutResolve(operation, ms, result) {
|
|
215
|
+
const promise = typeof operation === 'function' ? operation() : operation;
|
|
203
216
|
return Promise.race([
|
|
204
|
-
|
|
205
|
-
PromiseUtils.delayedResolve(ms, () => PromiseUtils.promiseState(
|
|
217
|
+
promise,
|
|
218
|
+
PromiseUtils.delayedResolve(ms, () => PromiseUtils.promiseState(promise)
|
|
206
219
|
.then(state => state === PromiseState.Pending ?
|
|
207
220
|
(typeof result === 'function' ? result() : result) :
|
|
208
221
|
{})),
|
|
209
222
|
]);
|
|
210
223
|
}
|
|
211
224
|
/**
|
|
212
|
-
*
|
|
213
|
-
* If timeout
|
|
214
|
-
* If timeout
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
* @param
|
|
219
|
-
* @param
|
|
220
|
-
* @
|
|
225
|
+
* Applies a timeout to a Promise or a function that returns a Promise.
|
|
226
|
+
* If the timeout occurs, rejects with the specified reason.
|
|
227
|
+
* If the timeout doesn't occur, the resolved result or rejection reason of the original Promise will be the outcome of the Promise returned from this function.
|
|
228
|
+
* If the 'reason' parameter is a function and timeout doesn't occur, the function won't be called.
|
|
229
|
+
* The rejection of the 'operation' parameter is not handled by this function, you may want to handle it outside of this function to avoid warnings like "(node:4330) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously".
|
|
230
|
+
*
|
|
231
|
+
* @param operation The original Promise or a function that returns a Promise for which the timeout will be applied.
|
|
232
|
+
* @param ms The number of milliseconds for the timeout.
|
|
233
|
+
* @param rejectReason The reason to reject with if the timeout occurs, or a function that supplies the reason.
|
|
234
|
+
* @return A new Promise that rejects with the specified reason if the timeout occurs.
|
|
221
235
|
*/
|
|
222
236
|
static timeoutReject(operation, ms, rejectReason) {
|
|
237
|
+
const promise = typeof operation === 'function' ? operation() : operation;
|
|
223
238
|
return Promise.race([
|
|
224
|
-
|
|
225
|
-
PromiseUtils.delayedReject(ms, () => PromiseUtils.promiseState(
|
|
239
|
+
promise,
|
|
240
|
+
PromiseUtils.delayedReject(ms, () => PromiseUtils.promiseState(promise)
|
|
226
241
|
.then(state => state === PromiseState.Pending ?
|
|
227
242
|
(typeof rejectReason === 'function' ? rejectReason() : rejectReason) :
|
|
228
243
|
{})),
|
|
@@ -232,7 +247,7 @@ class PromiseUtils {
|
|
|
232
247
|
* Get the state of the Promise.
|
|
233
248
|
* Please note that the returned value is a Promise, although it resolves immediately.
|
|
234
249
|
* @param p the Promise for which we would like to know its state
|
|
235
|
-
* @return A Promise that resolves immediately
|
|
250
|
+
* @return A Promise that resolves immediately containing the state of the input Promise
|
|
236
251
|
*/
|
|
237
252
|
static promiseState(p) {
|
|
238
253
|
const t = {};
|
|
@@ -257,16 +272,19 @@ class PromiseUtils {
|
|
|
257
272
|
previousState = await PromiseUtils.promiseState(previousResultPromise);
|
|
258
273
|
}
|
|
259
274
|
switch (previousState) {
|
|
260
|
-
case PromiseState.Pending: // concurrency
|
|
275
|
+
case PromiseState.Pending: { // concurrency
|
|
261
276
|
resultPromise = previousResultPromise.then(result => operation(PromiseState.Pending, PromiseState.Fulfilled, result), error => operation(PromiseState.Pending, PromiseState.Rejected, error));
|
|
262
277
|
break;
|
|
263
|
-
|
|
278
|
+
}
|
|
279
|
+
case undefined: { // no concurrency and no history
|
|
264
280
|
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
265
281
|
resultPromise = operation(undefined, undefined, undefined);
|
|
266
282
|
break;
|
|
267
|
-
|
|
283
|
+
}
|
|
284
|
+
default: { // no concurrency but with history
|
|
268
285
|
resultPromise = operation(previousState, previousState, await previousResultPromise.catch(error => error));
|
|
269
286
|
break;
|
|
287
|
+
}
|
|
270
288
|
}
|
|
271
289
|
PromiseUtils.synchronizationLocks.set(lock, resultPromise);
|
|
272
290
|
return resultPromise;
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@handy-common-utils/promise-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Promise related utilities",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"pretest": "eslint . --ext .ts",
|
|
7
7
|
"test": "nyc mocha",
|
|
8
8
|
"prepare": "shx rm -rf dist && tsc && es-check",
|
|
9
|
-
"preversion": "generate-api-docs-and-update-readme &&
|
|
9
|
+
"preversion": "generate-api-docs-and-update-readme && git add README.md"
|
|
10
10
|
},
|
|
11
11
|
"files": [
|
|
12
12
|
"package.json",
|
|
@@ -16,11 +16,8 @@
|
|
|
16
16
|
"types": "dist/promise-utils.d.ts",
|
|
17
17
|
"bin": {},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@handy-common-utils/dev-dependencies": "^1.
|
|
20
|
-
"@types/
|
|
21
|
-
"chai-as-promised": "^7.1.1",
|
|
22
|
-
"es-check": "^5.2.3",
|
|
23
|
-
"eslint": "^7.32.0"
|
|
19
|
+
"@handy-common-utils/dev-dependencies-mocha": "^1.3.1",
|
|
20
|
+
"@types/node": "^18.17.1"
|
|
24
21
|
},
|
|
25
22
|
"publishConfig": {
|
|
26
23
|
"access": "public"
|
|
@@ -34,10 +31,18 @@
|
|
|
34
31
|
"url": "https://github.com/handy-common-utils/promise-utils/issues"
|
|
35
32
|
},
|
|
36
33
|
"keywords": [
|
|
37
|
-
"
|
|
34
|
+
"promise",
|
|
38
35
|
"utils",
|
|
36
|
+
"retry",
|
|
37
|
+
"delay",
|
|
38
|
+
"resolve",
|
|
39
|
+
"reject",
|
|
39
40
|
"utilities"
|
|
40
41
|
],
|
|
41
42
|
"author": "James Hu",
|
|
42
|
-
"license": "Apache-2.0"
|
|
43
|
+
"license": "Apache-2.0",
|
|
44
|
+
"volta": {
|
|
45
|
+
"node": "18.17.0",
|
|
46
|
+
"npm": "9.6.7"
|
|
47
|
+
}
|
|
43
48
|
}
|