@sha1n/about-time 0.0.7 → 0.0.10
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 +48 -23
- package/dist/index.js +25 -11
- package/dist/lib/delay.js +46 -0
- package/dist/lib/eventually.js +44 -0
- package/dist/lib/retry.js +7 -6
- package/dist/lib/stopwatch.js +15 -0
- package/dist/lib/timeout.js +45 -0
- package/dist/lib/toMilliseconds.js +14 -0
- package/dist/lib/types.js +23 -0
- package/dist/lib/utilities.js +34 -20
- package/dist/types/index.d.ts +6 -2
- package/dist/types/lib/delay.d.ts +26 -0
- package/dist/types/lib/eventually.d.ts +14 -0
- package/dist/types/lib/retry.d.ts +1 -1
- package/dist/types/lib/stopwatch.d.ts +7 -0
- package/dist/types/lib/timeout.d.ts +11 -0
- package/dist/types/lib/toMilliseconds.d.ts +10 -0
- package/dist/types/lib/types.d.ts +48 -0
- package/dist/types/lib/utilities.d.ts +43 -16
- package/index.ts +6 -2
- package/lib/delay.ts +48 -0
- package/lib/eventually.ts +45 -0
- package/lib/retry.ts +3 -2
- package/lib/stopwatch.ts +15 -0
- package/lib/timeout.ts +50 -0
- package/lib/{timeunit.ts → toMilliseconds.ts} +2 -13
- package/lib/types.ts +54 -0
- package/package.json +14 -13
- package/lib/utilities.ts +0 -129
package/README.md
CHANGED
|
@@ -12,18 +12,20 @@ A collection of essential time related utilities.
|
|
|
12
12
|
- [About-Time](#about-time)
|
|
13
13
|
- [Install](#install)
|
|
14
14
|
- [Utilities & Features](#utilities--features)
|
|
15
|
-
- [
|
|
16
|
-
- [
|
|
17
|
-
- [
|
|
18
|
-
- [
|
|
19
|
-
- [
|
|
15
|
+
- [delay](#delay)
|
|
16
|
+
- [delayed](#delayed)
|
|
17
|
+
- [timeoutAround](#timeoutaround)
|
|
18
|
+
- [timeBounded](#timebounded)
|
|
19
|
+
- [sleep](#sleep)
|
|
20
|
+
- [stopwatch](#stopwatch)
|
|
21
|
+
- [until / eventually](#until--eventually)
|
|
20
22
|
- [Retry](#retry)
|
|
21
23
|
- [RetryPolicy](#retrypolicy)
|
|
22
24
|
- [Simple retry policy](#simple-retry-policy)
|
|
23
25
|
- [Fixed retry policy](#fixed-retry-policy)
|
|
24
26
|
- [Exponential backoff retry policy](#exponential-backoff-retry-policy)
|
|
25
|
-
- [
|
|
26
|
-
- [
|
|
27
|
+
- [retryAround](#retryaround)
|
|
28
|
+
- [retriable](#retriable)
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
# Install
|
|
@@ -32,25 +34,46 @@ npm i @sha1n/about-time
|
|
|
32
34
|
```
|
|
33
35
|
|
|
34
36
|
# Utilities & Features
|
|
35
|
-
##
|
|
37
|
+
## delay
|
|
36
38
|
```ts
|
|
37
|
-
//
|
|
38
|
-
await delay(action, 10
|
|
39
|
+
// Executes a function with delay and returns it's value
|
|
40
|
+
await delay(action, { time: 10 });
|
|
41
|
+
await delay(action, { time: 10, units: TimeUnit.Milliseconds });
|
|
42
|
+
await delay(action, { time: 10, units: TimeUnit.Milliseconds, unref: true });
|
|
39
43
|
```
|
|
40
44
|
|
|
41
|
-
##
|
|
45
|
+
## delayed
|
|
42
46
|
```ts
|
|
43
|
-
//
|
|
44
|
-
|
|
47
|
+
// Returns a new function that executes the specified action with delay and returns it's value
|
|
48
|
+
const delayedAction = delayed(action, { time: 10, units: TimeUnit.Milliseconds, unref: true });
|
|
49
|
+
const result = await delayedAction();
|
|
45
50
|
```
|
|
46
51
|
|
|
47
|
-
##
|
|
52
|
+
## timeoutAround
|
|
48
53
|
```ts
|
|
49
|
-
//
|
|
50
|
-
await
|
|
54
|
+
// Executes a function and guards it with a specified timeout
|
|
55
|
+
await timeoutAround(action, { time: 10 });
|
|
56
|
+
await timeoutAround(action, { time: 10, units: TimeUnit.Milliseconds });
|
|
57
|
+
await timeoutAround(action, { time: 10, units: TimeUnit.Milliseconds, unref: true });
|
|
51
58
|
```
|
|
52
59
|
|
|
53
|
-
##
|
|
60
|
+
## timeBounded
|
|
61
|
+
Wraps a given function with `timeoutAround` with the specified arguments.
|
|
62
|
+
```ts
|
|
63
|
+
const timeBoundAction = timeBounded(action, options);
|
|
64
|
+
const result = await timeBoundAction();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
## sleep
|
|
69
|
+
```ts
|
|
70
|
+
// Pauses execution for a specified amount of time
|
|
71
|
+
await sleep(10);
|
|
72
|
+
await sleep(10, { units: TimeUnit.Seconds });
|
|
73
|
+
await sleep(10, { units: TimeUnit.Seconds, unref: true });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## stopwatch
|
|
54
77
|
```ts
|
|
55
78
|
// Measure time between actions
|
|
56
79
|
const elapsed = stopwatch();
|
|
@@ -64,11 +87,13 @@ const elapsed1 = elapsed(TimeUnit.Milliseconds);
|
|
|
64
87
|
const elapsed2 = elapsed(TimeUnit.Seconds);
|
|
65
88
|
```
|
|
66
89
|
|
|
67
|
-
##
|
|
90
|
+
## until / eventually
|
|
68
91
|
```ts
|
|
69
|
-
//
|
|
70
|
-
await until(condition, {
|
|
71
|
-
await
|
|
92
|
+
// Waits for a condition to become true
|
|
93
|
+
await until(condition, { deadline: 10000 });
|
|
94
|
+
await until(condition, { deadline: 10000, interval: 100 });
|
|
95
|
+
await until(condition, { deadline: 10000, interval: 100, units: TimeUnit.Milliseconds });
|
|
96
|
+
await until(condition, { deadline: 10000, interval: 100, units: TimeUnit.Milliseconds, unref: true });
|
|
72
97
|
```
|
|
73
98
|
|
|
74
99
|
## Retry
|
|
@@ -98,14 +123,14 @@ interval<sub>i</sub> = min(limit, (exponential<sup>i</sup> - 1) / 2)
|
|
|
98
123
|
const retryPolicy = exponentialBackoffRetryPolicy(/* count = */10, /* opts?: { exponential?: number, limit?: number, units?: TimeUnit }*/);
|
|
99
124
|
```
|
|
100
125
|
|
|
101
|
-
###
|
|
126
|
+
### retryAround
|
|
102
127
|
Executes the given function with retries based on the specified policy and *optional* predicate.
|
|
103
128
|
The predicate provides control over which errors we want to retry on.
|
|
104
129
|
```ts
|
|
105
130
|
const result = await retryAround(action, retryPolicy, predicate);
|
|
106
131
|
```
|
|
107
132
|
|
|
108
|
-
###
|
|
133
|
+
### retriable
|
|
109
134
|
Wraps a given function with `retryAround` with the specified arguments.
|
|
110
135
|
```ts
|
|
111
136
|
const retriableAction = retriable(action, retryPolicy, predicate);
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
+
};
|
|
2
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.exponentialBackoffRetryPolicy = exports.simpleRetryPolicy = exports.fixedRetryPolicy = exports.retriable = exports.retryAround = exports.eventually = exports.until = exports.stopwatch = exports.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Object.defineProperty(exports, "toMilliseconds", { enumerable: true, get: function () { return
|
|
7
|
-
var
|
|
8
|
-
Object.defineProperty(exports, "
|
|
9
|
-
Object.defineProperty(exports, "
|
|
10
|
-
|
|
11
|
-
Object.defineProperty(exports, "
|
|
12
|
-
Object.defineProperty(exports, "
|
|
13
|
-
|
|
13
|
+
exports.exponentialBackoffRetryPolicy = exports.simpleRetryPolicy = exports.fixedRetryPolicy = exports.retriable = exports.retryAround = exports.eventually = exports.until = exports.stopwatch = exports.timeBounded = exports.timeoutAround = exports.delay = exports.sleep = exports.toMilliseconds = void 0;
|
|
14
|
+
__exportStar(require("./lib/types"), exports);
|
|
15
|
+
var toMilliseconds_1 = require("./lib/toMilliseconds");
|
|
16
|
+
Object.defineProperty(exports, "toMilliseconds", { enumerable: true, get: function () { return toMilliseconds_1.toMilliseconds; } });
|
|
17
|
+
var delay_1 = require("./lib/delay");
|
|
18
|
+
Object.defineProperty(exports, "sleep", { enumerable: true, get: function () { return delay_1.sleep; } });
|
|
19
|
+
Object.defineProperty(exports, "delay", { enumerable: true, get: function () { return delay_1.delay; } });
|
|
20
|
+
var timeout_1 = require("./lib/timeout");
|
|
21
|
+
Object.defineProperty(exports, "timeoutAround", { enumerable: true, get: function () { return timeout_1.timeoutAround; } });
|
|
22
|
+
Object.defineProperty(exports, "timeBounded", { enumerable: true, get: function () { return timeout_1.timeBounded; } });
|
|
23
|
+
var stopwatch_1 = require("./lib/stopwatch");
|
|
24
|
+
Object.defineProperty(exports, "stopwatch", { enumerable: true, get: function () { return stopwatch_1.stopwatch; } });
|
|
25
|
+
var eventually_1 = require("./lib/eventually");
|
|
26
|
+
Object.defineProperty(exports, "until", { enumerable: true, get: function () { return eventually_1.until; } });
|
|
27
|
+
Object.defineProperty(exports, "eventually", { enumerable: true, get: function () { return eventually_1.eventually; } });
|
|
14
28
|
var retry_1 = require("./lib/retry");
|
|
15
29
|
Object.defineProperty(exports, "retryAround", { enumerable: true, get: function () { return retry_1.retryAround; } });
|
|
16
30
|
Object.defineProperty(exports, "retriable", { enumerable: true, get: function () { return retry_1.retriable; } });
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.delayed = exports.delay = exports.sleep = void 0;
|
|
4
|
+
const toMilliseconds_1 = require("./toMilliseconds");
|
|
5
|
+
/**
|
|
6
|
+
* Zzzz...
|
|
7
|
+
*
|
|
8
|
+
* @param time the approximate time to sleep (expect it to be as accurate as setTimeout)
|
|
9
|
+
* @param options timer options minus the time property
|
|
10
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
11
|
+
*/
|
|
12
|
+
function sleep(time, options) {
|
|
13
|
+
return new Promise(resolve => {
|
|
14
|
+
const timeout = setTimeout(resolve, (0, toMilliseconds_1.toMilliseconds)(time, options === null || options === void 0 ? void 0 : options.units));
|
|
15
|
+
if (options === null || options === void 0 ? void 0 : options.unref) {
|
|
16
|
+
timeout.unref();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
exports.sleep = sleep;
|
|
21
|
+
/**
|
|
22
|
+
* Delays the execution of the specified action and returns its value.
|
|
23
|
+
*
|
|
24
|
+
* @param action a function to execute with delay
|
|
25
|
+
* @param options timer options
|
|
26
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
27
|
+
*/
|
|
28
|
+
async function delay(action, options) {
|
|
29
|
+
await sleep(options.time, options);
|
|
30
|
+
const result = await action();
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
exports.delay = delay;
|
|
34
|
+
/**
|
|
35
|
+
* Returns a new function that executes the specified action with delay.
|
|
36
|
+
*
|
|
37
|
+
* @param action a function to execute with delay
|
|
38
|
+
* @param options timer options
|
|
39
|
+
* @returns a new function.
|
|
40
|
+
*/
|
|
41
|
+
function delayed(action, options) {
|
|
42
|
+
return async () => {
|
|
43
|
+
return delay(action, options);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
exports.delayed = delayed;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.eventually = exports.until = void 0;
|
|
4
|
+
const toMilliseconds_1 = require("./toMilliseconds");
|
|
5
|
+
const types_1 = require("./types");
|
|
6
|
+
/**
|
|
7
|
+
* Awaits a specified condition to evaluate to true with or without a timeout.
|
|
8
|
+
*
|
|
9
|
+
* @param condition the condition to wait for
|
|
10
|
+
* @param options poll-options
|
|
11
|
+
* @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
|
|
12
|
+
*/
|
|
13
|
+
async function until(condition, options) {
|
|
14
|
+
const defaultInterval = 50;
|
|
15
|
+
const deadline = (options === null || options === void 0 ? void 0 : options.deadline) ? Date.now() + (0, toMilliseconds_1.toMilliseconds)(options.deadline, options.units) : Number.MAX_VALUE;
|
|
16
|
+
const interval = (options === null || options === void 0 ? void 0 : options.interval) ? (0, toMilliseconds_1.toMilliseconds)(options.interval, options.units) : defaultInterval;
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
const handle = setInterval(() => {
|
|
19
|
+
if (Date.now() > deadline) {
|
|
20
|
+
clearInterval(handle);
|
|
21
|
+
reject(new types_1.TimeoutError());
|
|
22
|
+
}
|
|
23
|
+
try {
|
|
24
|
+
if (condition()) {
|
|
25
|
+
clearInterval(handle);
|
|
26
|
+
resolve();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
clearInterval(handle);
|
|
31
|
+
reject(e);
|
|
32
|
+
}
|
|
33
|
+
}, interval);
|
|
34
|
+
if (options === null || options === void 0 ? void 0 : options.unref) {
|
|
35
|
+
handle.unref();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
exports.until = until;
|
|
40
|
+
/**
|
|
41
|
+
* Alias to `until`
|
|
42
|
+
*/
|
|
43
|
+
const eventually = until;
|
|
44
|
+
exports.eventually = eventually;
|
package/dist/lib/retry.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.exponentialBackoffRetryPolicy = exports.simpleRetryPolicy = exports.fixedRetryPolicy = exports.retriable = exports.retryAround = void 0;
|
|
4
|
-
const
|
|
5
|
-
const
|
|
4
|
+
const toMilliseconds_1 = require("./toMilliseconds");
|
|
5
|
+
const delay_1 = require("./delay");
|
|
6
|
+
const types_1 = require("./types");
|
|
6
7
|
class SimpleRetryPolicy {
|
|
7
8
|
constructor(count, interval, units) {
|
|
8
9
|
this.count = count;
|
|
9
|
-
this.interval = (0,
|
|
10
|
+
this.interval = (0, toMilliseconds_1.toMilliseconds)(interval, units);
|
|
10
11
|
}
|
|
11
12
|
*intervals() {
|
|
12
13
|
let count = this.count;
|
|
@@ -18,7 +19,7 @@ class SimpleRetryPolicy {
|
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
21
|
class ExponentialBackoffRetryPolicy {
|
|
21
|
-
constructor(count, exponential = 2, limit = Infinity, units =
|
|
22
|
+
constructor(count, exponential = 2, limit = Infinity, units = types_1.TimeUnit.Milliseconds) {
|
|
22
23
|
this.count = count;
|
|
23
24
|
this.exponential = exponential;
|
|
24
25
|
this.limit = limit;
|
|
@@ -37,7 +38,7 @@ class ExponentialBackoffRetryPolicy {
|
|
|
37
38
|
class FixedRetryPolicy {
|
|
38
39
|
constructor(intervals, units) {
|
|
39
40
|
this._intervals = intervals.reduceRight((result, v) => {
|
|
40
|
-
result.push((0,
|
|
41
|
+
result.push((0, toMilliseconds_1.toMilliseconds)(v, units));
|
|
41
42
|
return result;
|
|
42
43
|
}, []);
|
|
43
44
|
}
|
|
@@ -73,7 +74,7 @@ async function retryAround(action, policy, predicate = () => true) {
|
|
|
73
74
|
if (next.done || !predicate(e)) {
|
|
74
75
|
throw e;
|
|
75
76
|
}
|
|
76
|
-
await (0,
|
|
77
|
+
await (0, delay_1.sleep)(next.value);
|
|
77
78
|
}
|
|
78
79
|
} while (!next.done);
|
|
79
80
|
throw new Error('Unexpected error. This is most likely a bug.');
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stopwatch = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
/**
|
|
6
|
+
* Return a function that returns the elapsed time relative to this call.
|
|
7
|
+
* @returns a function
|
|
8
|
+
*/
|
|
9
|
+
function stopwatch() {
|
|
10
|
+
const startTime = Date.now();
|
|
11
|
+
return (units) => {
|
|
12
|
+
return (Date.now() - startTime) / (units || types_1.TimeUnit.Milliseconds);
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
exports.stopwatch = stopwatch;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.timeoutAround = exports.timeBounded = void 0;
|
|
4
|
+
const toMilliseconds_1 = require("./toMilliseconds");
|
|
5
|
+
const types_1 = require("./types");
|
|
6
|
+
/**
|
|
7
|
+
* Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
|
|
8
|
+
*
|
|
9
|
+
* @param action an action to execute with timeout
|
|
10
|
+
* @param options timer options
|
|
11
|
+
* @returns the action result
|
|
12
|
+
*/
|
|
13
|
+
async function timeoutAround(action, options) {
|
|
14
|
+
const promisedAction = new Promise((resolve, reject) => {
|
|
15
|
+
try {
|
|
16
|
+
resolve(action());
|
|
17
|
+
}
|
|
18
|
+
catch (e) {
|
|
19
|
+
reject(e);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
const race = new Promise((resolve, reject) => {
|
|
23
|
+
const timer = setTimeout(() => {
|
|
24
|
+
reject(new types_1.TimeoutError());
|
|
25
|
+
}, (0, toMilliseconds_1.toMilliseconds)(options.time, options.units));
|
|
26
|
+
if (options.unref) {
|
|
27
|
+
timer.unref();
|
|
28
|
+
}
|
|
29
|
+
return Promise.resolve(promisedAction).then(r => {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
resolve(r);
|
|
32
|
+
}, err => {
|
|
33
|
+
clearTimeout(timer);
|
|
34
|
+
reject(err);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
return race;
|
|
38
|
+
}
|
|
39
|
+
exports.timeoutAround = timeoutAround;
|
|
40
|
+
function timeBounded(action, options) {
|
|
41
|
+
return () => {
|
|
42
|
+
return timeoutAround(action, options);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
exports.timeBounded = timeBounded;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toMilliseconds = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Converts time value in other units to milliseconds.
|
|
6
|
+
*
|
|
7
|
+
* @param time a time value to be converted
|
|
8
|
+
* @param units the units of time
|
|
9
|
+
* @returns the time value in milliseconds
|
|
10
|
+
*/
|
|
11
|
+
function toMilliseconds(time, units) {
|
|
12
|
+
return time * (units ? units : 1);
|
|
13
|
+
}
|
|
14
|
+
exports.toMilliseconds = toMilliseconds;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TimeoutError = exports.TimeUnit = void 0;
|
|
4
|
+
var TimeUnit;
|
|
5
|
+
(function (TimeUnit) {
|
|
6
|
+
TimeUnit[TimeUnit["Milliseconds"] = 1] = "Milliseconds";
|
|
7
|
+
TimeUnit[TimeUnit["Millisecond"] = 1] = "Millisecond";
|
|
8
|
+
TimeUnit[TimeUnit["Seconds"] = 1000] = "Seconds";
|
|
9
|
+
TimeUnit[TimeUnit["Second"] = 1000] = "Second";
|
|
10
|
+
TimeUnit[TimeUnit["Minutes"] = 60000] = "Minutes";
|
|
11
|
+
TimeUnit[TimeUnit["Minute"] = 60000] = "Minute";
|
|
12
|
+
TimeUnit[TimeUnit["Hours"] = 3600000] = "Hours";
|
|
13
|
+
TimeUnit[TimeUnit["Hour"] = 3600000] = "Hour";
|
|
14
|
+
TimeUnit[TimeUnit["Days"] = 86400000] = "Days";
|
|
15
|
+
TimeUnit[TimeUnit["Day"] = 86400000] = "Day";
|
|
16
|
+
})(TimeUnit || (TimeUnit = {}));
|
|
17
|
+
exports.TimeUnit = TimeUnit;
|
|
18
|
+
class TimeoutError extends Error {
|
|
19
|
+
constructor(message) {
|
|
20
|
+
super(message || 'Timeout');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.TimeoutError = TimeoutError;
|
package/dist/lib/utilities.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.eventually = exports.until = exports.stopwatch = exports.delay = exports.sleep = exports.
|
|
3
|
+
exports.eventually = exports.until = exports.stopwatch = exports.delay = exports.sleep = exports.timeBounded = exports.timeoutAround = void 0;
|
|
4
4
|
const timeunit_1 = require("./timeunit");
|
|
5
5
|
class TimeoutError extends Error {
|
|
6
6
|
constructor(message) {
|
|
@@ -10,13 +10,16 @@ class TimeoutError extends Error {
|
|
|
10
10
|
/**
|
|
11
11
|
* Zzzz...
|
|
12
12
|
*
|
|
13
|
-
* @param time time to sleep
|
|
14
|
-
* @param
|
|
13
|
+
* @param time the approximate time to sleep (expect it to be as accurate as setTimeout)
|
|
14
|
+
* @param options timer options minus the time property
|
|
15
15
|
* @returns a promise that resolves when the specified time has elapsed.
|
|
16
16
|
*/
|
|
17
|
-
function sleep(time,
|
|
17
|
+
function sleep(time, options) {
|
|
18
18
|
return new Promise(resolve => {
|
|
19
|
-
setTimeout(resolve, (0, timeunit_1.toMilliseconds)(time, units));
|
|
19
|
+
const timeout = setTimeout(resolve, (0, timeunit_1.toMilliseconds)(time, options === null || options === void 0 ? void 0 : options.units));
|
|
20
|
+
if (options === null || options === void 0 ? void 0 : options.unref) {
|
|
21
|
+
timeout.unref();
|
|
22
|
+
}
|
|
20
23
|
});
|
|
21
24
|
}
|
|
22
25
|
exports.sleep = sleep;
|
|
@@ -24,17 +27,17 @@ exports.sleep = sleep;
|
|
|
24
27
|
* Delays the execution of the specified action and returns its value.
|
|
25
28
|
*
|
|
26
29
|
* @param action a function to execute with delay
|
|
27
|
-
* @param
|
|
28
|
-
* @param units the units on time
|
|
30
|
+
* @param options timer options
|
|
29
31
|
* @returns a promise that resolves when the specified time has elapsed.
|
|
30
32
|
*/
|
|
31
|
-
function delay(action,
|
|
33
|
+
function delay(action, options) {
|
|
34
|
+
const { time, units, unref } = options;
|
|
32
35
|
const delayMs = (0, timeunit_1.toMilliseconds)(time, units);
|
|
33
36
|
return new Promise((resolve, reject) => {
|
|
34
37
|
const timer = setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
+
if (unref) {
|
|
39
|
+
timer.unref();
|
|
40
|
+
}
|
|
38
41
|
});
|
|
39
42
|
}
|
|
40
43
|
exports.delay = delay;
|
|
@@ -53,13 +56,13 @@ exports.stopwatch = stopwatch;
|
|
|
53
56
|
* Awaits a specified condition to evaluate to true with or without a timeout.
|
|
54
57
|
*
|
|
55
58
|
* @param condition the condition to wait for
|
|
56
|
-
* @param
|
|
59
|
+
* @param options poll-options
|
|
57
60
|
* @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
|
|
58
61
|
*/
|
|
59
|
-
async function until(condition,
|
|
62
|
+
async function until(condition, options) {
|
|
60
63
|
const defaultInterval = 50;
|
|
61
|
-
const deadline =
|
|
62
|
-
const interval = (
|
|
64
|
+
const deadline = (options === null || options === void 0 ? void 0 : options.deadline) ? Date.now() + (0, timeunit_1.toMilliseconds)(options.deadline, options.units) : Number.MAX_VALUE;
|
|
65
|
+
const interval = (options === null || options === void 0 ? void 0 : options.interval) ? (0, timeunit_1.toMilliseconds)(options.interval, options.units) : defaultInterval;
|
|
63
66
|
return new Promise((resolve, reject) => {
|
|
64
67
|
const handle = setInterval(() => {
|
|
65
68
|
if (Date.now() > deadline) {
|
|
@@ -77,6 +80,9 @@ async function until(condition, opts) {
|
|
|
77
80
|
reject(e);
|
|
78
81
|
}
|
|
79
82
|
}, interval);
|
|
83
|
+
if (options === null || options === void 0 ? void 0 : options.unref) {
|
|
84
|
+
handle.unref();
|
|
85
|
+
}
|
|
80
86
|
});
|
|
81
87
|
}
|
|
82
88
|
exports.until = until;
|
|
@@ -89,11 +95,10 @@ exports.eventually = eventually;
|
|
|
89
95
|
* Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
|
|
90
96
|
*
|
|
91
97
|
* @param action an action to execute with timeout
|
|
92
|
-
* @param
|
|
93
|
-
* @param units the time units
|
|
98
|
+
* @param options timer options
|
|
94
99
|
* @returns the action result
|
|
95
100
|
*/
|
|
96
|
-
async function
|
|
101
|
+
async function timeoutAround(action, options) {
|
|
97
102
|
const promisedAction = new Promise((resolve, reject) => {
|
|
98
103
|
try {
|
|
99
104
|
resolve(action());
|
|
@@ -105,7 +110,10 @@ async function withTimeout(action, timeout, units) {
|
|
|
105
110
|
const race = new Promise((resolve, reject) => {
|
|
106
111
|
const timer = setTimeout(() => {
|
|
107
112
|
reject(new TimeoutError());
|
|
108
|
-
}, (0, timeunit_1.toMilliseconds)(
|
|
113
|
+
}, (0, timeunit_1.toMilliseconds)(options.time, options.units));
|
|
114
|
+
if (options.unref) {
|
|
115
|
+
timer.unref();
|
|
116
|
+
}
|
|
109
117
|
return Promise.resolve(promisedAction).then(r => {
|
|
110
118
|
clearTimeout(timer);
|
|
111
119
|
resolve(r);
|
|
@@ -116,4 +124,10 @@ async function withTimeout(action, timeout, units) {
|
|
|
116
124
|
});
|
|
117
125
|
return race;
|
|
118
126
|
}
|
|
119
|
-
exports.
|
|
127
|
+
exports.timeoutAround = timeoutAround;
|
|
128
|
+
function timeBounded(action, options) {
|
|
129
|
+
return () => {
|
|
130
|
+
return timeoutAround(action, options);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
exports.timeBounded = timeBounded;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
export
|
|
2
|
-
export {
|
|
1
|
+
export * from './lib/types';
|
|
2
|
+
export { toMilliseconds } from './lib/toMilliseconds';
|
|
3
|
+
export { sleep, delay } from './lib/delay';
|
|
4
|
+
export { timeoutAround, timeBounded } from './lib/timeout';
|
|
5
|
+
export { stopwatch } from './lib/stopwatch';
|
|
6
|
+
export { until, eventually } from './lib/eventually';
|
|
3
7
|
export { RetryPolicy, retryAround, retriable, fixedRetryPolicy, simpleRetryPolicy, exponentialBackoffRetryPolicy } from './lib/retry';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { TimerOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Zzzz...
|
|
4
|
+
*
|
|
5
|
+
* @param time the approximate time to sleep (expect it to be as accurate as setTimeout)
|
|
6
|
+
* @param options timer options minus the time property
|
|
7
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
8
|
+
*/
|
|
9
|
+
declare function sleep(time: number, options?: Omit<TimerOptions, 'time'>): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Delays the execution of the specified action and returns its value.
|
|
12
|
+
*
|
|
13
|
+
* @param action a function to execute with delay
|
|
14
|
+
* @param options timer options
|
|
15
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
16
|
+
*/
|
|
17
|
+
declare function delay<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T>;
|
|
18
|
+
/**
|
|
19
|
+
* Returns a new function that executes the specified action with delay.
|
|
20
|
+
*
|
|
21
|
+
* @param action a function to execute with delay
|
|
22
|
+
* @param options timer options
|
|
23
|
+
* @returns a new function.
|
|
24
|
+
*/
|
|
25
|
+
declare function delayed<T>(action: () => T | Promise<T>, options: TimerOptions): () => Promise<T>;
|
|
26
|
+
export { sleep, delay, delayed };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PollOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Awaits a specified condition to evaluate to true with or without a timeout.
|
|
4
|
+
*
|
|
5
|
+
* @param condition the condition to wait for
|
|
6
|
+
* @param options poll-options
|
|
7
|
+
* @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
|
|
8
|
+
*/
|
|
9
|
+
declare function until(condition: () => boolean, options?: PollOptions): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Alias to `until`
|
|
12
|
+
*/
|
|
13
|
+
declare const eventually: typeof until;
|
|
14
|
+
export { until, eventually };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { TimerOptions } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
|
|
4
|
+
*
|
|
5
|
+
* @param action an action to execute with timeout
|
|
6
|
+
* @param options timer options
|
|
7
|
+
* @returns the action result
|
|
8
|
+
*/
|
|
9
|
+
declare function timeoutAround<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T>;
|
|
10
|
+
declare function timeBounded<T>(action: () => T | Promise<T>, options: TimerOptions): () => Promise<T>;
|
|
11
|
+
export { timeBounded, timeoutAround };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { TimeUnit } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Converts time value in other units to milliseconds.
|
|
4
|
+
*
|
|
5
|
+
* @param time a time value to be converted
|
|
6
|
+
* @param units the units of time
|
|
7
|
+
* @returns the time value in milliseconds
|
|
8
|
+
*/
|
|
9
|
+
declare function toMilliseconds(time: number, units?: TimeUnit): number;
|
|
10
|
+
export { toMilliseconds };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
declare enum TimeUnit {
|
|
2
|
+
Milliseconds = 1,
|
|
3
|
+
Millisecond = 1,
|
|
4
|
+
Seconds = 1000,
|
|
5
|
+
Second = 1000,
|
|
6
|
+
Minutes = 60000,
|
|
7
|
+
Minute = 60000,
|
|
8
|
+
Hours = 3600000,
|
|
9
|
+
Hour = 3600000,
|
|
10
|
+
Days = 86400000,
|
|
11
|
+
Day = 86400000
|
|
12
|
+
}
|
|
13
|
+
declare class TimeoutError extends Error {
|
|
14
|
+
constructor(message?: string);
|
|
15
|
+
}
|
|
16
|
+
declare type TimerOptions = {
|
|
17
|
+
/**
|
|
18
|
+
* The time to set
|
|
19
|
+
*/
|
|
20
|
+
readonly time: number;
|
|
21
|
+
/**
|
|
22
|
+
* Optional units for the specified time
|
|
23
|
+
*/
|
|
24
|
+
readonly units?: TimeUnit;
|
|
25
|
+
/**
|
|
26
|
+
* Whether to call unref on the timer
|
|
27
|
+
*/
|
|
28
|
+
readonly unref?: boolean;
|
|
29
|
+
};
|
|
30
|
+
declare type PollOptions = {
|
|
31
|
+
/**
|
|
32
|
+
* The poll interval to set
|
|
33
|
+
*/
|
|
34
|
+
readonly interval?: number;
|
|
35
|
+
/**
|
|
36
|
+
* The overall deadline to set
|
|
37
|
+
*/
|
|
38
|
+
readonly deadline?: number;
|
|
39
|
+
/**
|
|
40
|
+
* Time units for specified time properties
|
|
41
|
+
*/
|
|
42
|
+
readonly units?: TimeUnit;
|
|
43
|
+
/**
|
|
44
|
+
* Whether to call unref on any intervals/timers
|
|
45
|
+
*/
|
|
46
|
+
readonly unref?: boolean;
|
|
47
|
+
};
|
|
48
|
+
export { TimeUnit, PollOptions, TimeoutError, TimerOptions };
|
|
@@ -1,21 +1,52 @@
|
|
|
1
1
|
import { TimeUnit } from './timeunit';
|
|
2
|
+
declare type TimerOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* The time to set
|
|
5
|
+
*/
|
|
6
|
+
readonly time: number;
|
|
7
|
+
/**
|
|
8
|
+
* Optional units for the specified time
|
|
9
|
+
*/
|
|
10
|
+
readonly units?: TimeUnit;
|
|
11
|
+
/**
|
|
12
|
+
* Whether to call unref on the timer
|
|
13
|
+
*/
|
|
14
|
+
readonly unref?: boolean;
|
|
15
|
+
};
|
|
16
|
+
declare type PollOptions = {
|
|
17
|
+
/**
|
|
18
|
+
* The poll interval to set
|
|
19
|
+
*/
|
|
20
|
+
readonly interval?: number;
|
|
21
|
+
/**
|
|
22
|
+
* The overall deadline to set
|
|
23
|
+
*/
|
|
24
|
+
readonly deadline?: number;
|
|
25
|
+
/**
|
|
26
|
+
* Time units for specified time properties
|
|
27
|
+
*/
|
|
28
|
+
readonly units?: TimeUnit;
|
|
29
|
+
/**
|
|
30
|
+
* Whether to call unref on any intervals/timers
|
|
31
|
+
*/
|
|
32
|
+
readonly unref?: boolean;
|
|
33
|
+
};
|
|
2
34
|
/**
|
|
3
35
|
* Zzzz...
|
|
4
36
|
*
|
|
5
|
-
* @param time time to sleep
|
|
6
|
-
* @param
|
|
37
|
+
* @param time the approximate time to sleep (expect it to be as accurate as setTimeout)
|
|
38
|
+
* @param options timer options minus the time property
|
|
7
39
|
* @returns a promise that resolves when the specified time has elapsed.
|
|
8
40
|
*/
|
|
9
|
-
declare function sleep(time: number,
|
|
41
|
+
declare function sleep(time: number, options?: Omit<TimerOptions, 'time'>): Promise<void>;
|
|
10
42
|
/**
|
|
11
43
|
* Delays the execution of the specified action and returns its value.
|
|
12
44
|
*
|
|
13
45
|
* @param action a function to execute with delay
|
|
14
|
-
* @param
|
|
15
|
-
* @param units the units on time
|
|
46
|
+
* @param options timer options
|
|
16
47
|
* @returns a promise that resolves when the specified time has elapsed.
|
|
17
48
|
*/
|
|
18
|
-
declare function delay<T>(action: () => T | Promise<T>,
|
|
49
|
+
declare function delay<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T>;
|
|
19
50
|
/**
|
|
20
51
|
* Return a function that returns the elapsed time relative to this call.
|
|
21
52
|
* @returns a function
|
|
@@ -25,14 +56,10 @@ declare function stopwatch(): (units?: TimeUnit) => number;
|
|
|
25
56
|
* Awaits a specified condition to evaluate to true with or without a timeout.
|
|
26
57
|
*
|
|
27
58
|
* @param condition the condition to wait for
|
|
28
|
-
* @param
|
|
59
|
+
* @param options poll-options
|
|
29
60
|
* @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
|
|
30
61
|
*/
|
|
31
|
-
declare function until(condition: () => boolean,
|
|
32
|
-
interval?: number;
|
|
33
|
-
timeout: number;
|
|
34
|
-
units?: TimeUnit;
|
|
35
|
-
}): Promise<void>;
|
|
62
|
+
declare function until(condition: () => boolean, options?: PollOptions): Promise<void>;
|
|
36
63
|
/**
|
|
37
64
|
* Alias to `until`
|
|
38
65
|
*/
|
|
@@ -41,9 +68,9 @@ declare const eventually: typeof until;
|
|
|
41
68
|
* Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
|
|
42
69
|
*
|
|
43
70
|
* @param action an action to execute with timeout
|
|
44
|
-
* @param
|
|
45
|
-
* @param units the time units
|
|
71
|
+
* @param options timer options
|
|
46
72
|
* @returns the action result
|
|
47
73
|
*/
|
|
48
|
-
declare function
|
|
49
|
-
|
|
74
|
+
declare function timeoutAround<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T>;
|
|
75
|
+
declare function timeBounded<T>(action: () => T | Promise<T>, options: TimerOptions): () => Promise<T>;
|
|
76
|
+
export { timeoutAround, timeBounded, sleep, delay, stopwatch, until, eventually };
|
package/index.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
export
|
|
2
|
-
export {
|
|
1
|
+
export * from './lib/types';
|
|
2
|
+
export { toMilliseconds } from './lib/toMilliseconds';
|
|
3
|
+
export { sleep, delay } from './lib/delay';
|
|
4
|
+
export { timeoutAround, timeBounded } from './lib/timeout';
|
|
5
|
+
export { stopwatch } from './lib/stopwatch';
|
|
6
|
+
export { until, eventually } from './lib/eventually';
|
|
3
7
|
export {
|
|
4
8
|
RetryPolicy,
|
|
5
9
|
retryAround,
|
package/lib/delay.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { toMilliseconds } from './toMilliseconds';
|
|
2
|
+
import { TimerOptions } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Zzzz...
|
|
6
|
+
*
|
|
7
|
+
* @param time the approximate time to sleep (expect it to be as accurate as setTimeout)
|
|
8
|
+
* @param options timer options minus the time property
|
|
9
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
10
|
+
*/
|
|
11
|
+
function sleep(time: number, options?: Omit<TimerOptions, 'time'>): Promise<void> {
|
|
12
|
+
return new Promise(resolve => {
|
|
13
|
+
const timeout = setTimeout(resolve, toMilliseconds(time, options?.units));
|
|
14
|
+
|
|
15
|
+
if (options?.unref) {
|
|
16
|
+
timeout.unref();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Delays the execution of the specified action and returns its value.
|
|
23
|
+
*
|
|
24
|
+
* @param action a function to execute with delay
|
|
25
|
+
* @param options timer options
|
|
26
|
+
* @returns a promise that resolves when the specified time has elapsed.
|
|
27
|
+
*/
|
|
28
|
+
async function delay<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T> {
|
|
29
|
+
await sleep(options.time, options);
|
|
30
|
+
const result = await action();
|
|
31
|
+
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Returns a new function that executes the specified action with delay.
|
|
37
|
+
*
|
|
38
|
+
* @param action a function to execute with delay
|
|
39
|
+
* @param options timer options
|
|
40
|
+
* @returns a new function.
|
|
41
|
+
*/
|
|
42
|
+
function delayed<T>(action: () => T | Promise<T>, options: TimerOptions): () => Promise<T> {
|
|
43
|
+
return async () => {
|
|
44
|
+
return delay(action, options);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { sleep, delay, delayed };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { toMilliseconds } from './toMilliseconds';
|
|
2
|
+
import { PollOptions, TimeoutError } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Awaits a specified condition to evaluate to true with or without a timeout.
|
|
6
|
+
*
|
|
7
|
+
* @param condition the condition to wait for
|
|
8
|
+
* @param options poll-options
|
|
9
|
+
* @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
|
|
10
|
+
*/
|
|
11
|
+
async function until(condition: () => boolean, options?: PollOptions): Promise<void> {
|
|
12
|
+
const defaultInterval = 50;
|
|
13
|
+
const deadline = options?.deadline ? Date.now() + toMilliseconds(options.deadline, options.units) : Number.MAX_VALUE;
|
|
14
|
+
const interval = options?.interval ? toMilliseconds(options.interval, options.units) : defaultInterval;
|
|
15
|
+
|
|
16
|
+
return new Promise<void>((resolve, reject) => {
|
|
17
|
+
const handle = setInterval(() => {
|
|
18
|
+
if (Date.now() > deadline) {
|
|
19
|
+
clearInterval(handle);
|
|
20
|
+
reject(new TimeoutError());
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
if (condition()) {
|
|
25
|
+
clearInterval(handle);
|
|
26
|
+
resolve();
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {
|
|
29
|
+
clearInterval(handle);
|
|
30
|
+
reject(e);
|
|
31
|
+
}
|
|
32
|
+
}, interval);
|
|
33
|
+
|
|
34
|
+
if (options?.unref) {
|
|
35
|
+
handle.unref();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Alias to `until`
|
|
42
|
+
*/
|
|
43
|
+
const eventually = until;
|
|
44
|
+
|
|
45
|
+
export { until, eventually };
|
package/lib/retry.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { sleep } from './
|
|
1
|
+
import { toMilliseconds } from './toMilliseconds';
|
|
2
|
+
import { sleep } from './delay';
|
|
3
|
+
import { TimeUnit } from './types';
|
|
3
4
|
|
|
4
5
|
interface RetryPolicy {
|
|
5
6
|
intervals(): Iterable<number>;
|
package/lib/stopwatch.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { TimeUnit } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Return a function that returns the elapsed time relative to this call.
|
|
5
|
+
* @returns a function
|
|
6
|
+
*/
|
|
7
|
+
function stopwatch(): (units?: TimeUnit) => number {
|
|
8
|
+
const startTime = Date.now();
|
|
9
|
+
|
|
10
|
+
return (units?: TimeUnit) => {
|
|
11
|
+
return (Date.now() - startTime) / (units || TimeUnit.Milliseconds);
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { stopwatch };
|
package/lib/timeout.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { toMilliseconds } from './toMilliseconds';
|
|
2
|
+
import { TimerOptions, TimeoutError } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
|
|
6
|
+
*
|
|
7
|
+
* @param action an action to execute with timeout
|
|
8
|
+
* @param options timer options
|
|
9
|
+
* @returns the action result
|
|
10
|
+
*/
|
|
11
|
+
async function timeoutAround<T>(action: () => T | Promise<T>, options: TimerOptions): Promise<T> {
|
|
12
|
+
const promisedAction = new Promise<T>((resolve, reject) => {
|
|
13
|
+
try {
|
|
14
|
+
resolve(action());
|
|
15
|
+
} catch (e) {
|
|
16
|
+
reject(e);
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const race = new Promise<T>((resolve, reject) => {
|
|
21
|
+
const timer = setTimeout(() => {
|
|
22
|
+
reject(new TimeoutError());
|
|
23
|
+
}, toMilliseconds(options.time, options.units));
|
|
24
|
+
|
|
25
|
+
if (options.unref) {
|
|
26
|
+
timer.unref();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return Promise.resolve(promisedAction).then(
|
|
30
|
+
r => {
|
|
31
|
+
clearTimeout(timer);
|
|
32
|
+
resolve(r);
|
|
33
|
+
},
|
|
34
|
+
err => {
|
|
35
|
+
clearTimeout(timer);
|
|
36
|
+
reject(err);
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
return race;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function timeBounded<T>(action: () => T | Promise<T>, options: TimerOptions): () => Promise<T> {
|
|
45
|
+
return () => {
|
|
46
|
+
return timeoutAround(action, options);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { timeBounded, timeoutAround };
|
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Milliseconds = 1,
|
|
3
|
-
Millisecond = Milliseconds,
|
|
4
|
-
Seconds = 1000,
|
|
5
|
-
Second = Seconds,
|
|
6
|
-
Minutes = 1000 * 60,
|
|
7
|
-
Minute = Minutes,
|
|
8
|
-
Hours = 1000 * 60 * 60,
|
|
9
|
-
Hour = Hours,
|
|
10
|
-
Days = 1000 * 60 * 60 * 24,
|
|
11
|
-
Day = Days
|
|
12
|
-
}
|
|
1
|
+
import { TimeUnit } from './types';
|
|
13
2
|
|
|
14
3
|
/**
|
|
15
4
|
* Converts time value in other units to milliseconds.
|
|
@@ -22,4 +11,4 @@ function toMilliseconds(time: number, units?: TimeUnit): number {
|
|
|
22
11
|
return time * (units ? units : 1);
|
|
23
12
|
}
|
|
24
13
|
|
|
25
|
-
export {
|
|
14
|
+
export { toMilliseconds };
|
package/lib/types.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
enum TimeUnit {
|
|
2
|
+
Milliseconds = 1,
|
|
3
|
+
Millisecond = Milliseconds,
|
|
4
|
+
Seconds = 1000,
|
|
5
|
+
Second = Seconds,
|
|
6
|
+
Minutes = 1000 * 60,
|
|
7
|
+
Minute = Minutes,
|
|
8
|
+
Hours = 1000 * 60 * 60,
|
|
9
|
+
Hour = Hours,
|
|
10
|
+
Days = 1000 * 60 * 60 * 24,
|
|
11
|
+
Day = Days
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class TimeoutError extends Error {
|
|
15
|
+
constructor(message?: string) {
|
|
16
|
+
super(message || 'Timeout');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type TimerOptions = {
|
|
21
|
+
/**
|
|
22
|
+
* The time to set
|
|
23
|
+
*/
|
|
24
|
+
readonly time: number;
|
|
25
|
+
/**
|
|
26
|
+
* Optional units for the specified time
|
|
27
|
+
*/
|
|
28
|
+
readonly units?: TimeUnit;
|
|
29
|
+
/**
|
|
30
|
+
* Whether to call unref on the timer
|
|
31
|
+
*/
|
|
32
|
+
readonly unref?: boolean;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
type PollOptions = {
|
|
36
|
+
/**
|
|
37
|
+
* The poll interval to set
|
|
38
|
+
*/
|
|
39
|
+
readonly interval?: number;
|
|
40
|
+
/**
|
|
41
|
+
* The overall deadline to set
|
|
42
|
+
*/
|
|
43
|
+
readonly deadline?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Time units for specified time properties
|
|
46
|
+
*/
|
|
47
|
+
readonly units?: TimeUnit;
|
|
48
|
+
/**
|
|
49
|
+
* Whether to call unref on any intervals/timers
|
|
50
|
+
*/
|
|
51
|
+
readonly unref?: boolean;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export { TimeUnit, PollOptions, TimeoutError, TimerOptions };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sha1n/about-time",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.10",
|
|
4
4
|
"description": "A set of essential time related utilities",
|
|
5
5
|
"repository": "https://github.com/sha1n/about-time",
|
|
6
6
|
"author": "Shai Nagar",
|
|
@@ -22,38 +22,39 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"clean": "rm -rf ./dist",
|
|
25
|
-
"prebuild": "yarn run clean",
|
|
26
25
|
"build": "tsc",
|
|
27
|
-
"test": "DEBUG=error:* jest --coverage",
|
|
28
26
|
"lint": "eslint --fix --ext .js,.ts .",
|
|
29
|
-
"
|
|
30
|
-
"
|
|
27
|
+
"jest": "DEBUG='error:*' jest --coverage",
|
|
28
|
+
"test": "run jest && run lint",
|
|
29
|
+
"prepublish": "run build"
|
|
31
30
|
},
|
|
32
|
-
"dependencies": {},
|
|
33
31
|
"devDependencies": {
|
|
34
32
|
"@types/chance": "^1.1.3",
|
|
33
|
+
"@types/is-ci": "^3.0.0",
|
|
35
34
|
"@types/jest": "^27.4.0",
|
|
36
35
|
"@types/node": "^17.0.8",
|
|
37
36
|
"@typescript-eslint/eslint-plugin": "^5.1.0",
|
|
38
37
|
"@typescript-eslint/parser": "^5.1.0",
|
|
39
38
|
"chance": "^1.1.8",
|
|
40
|
-
"eslint": "^
|
|
39
|
+
"eslint": "^8.9.0",
|
|
41
40
|
"eslint-config-prettier": "^8.3.0",
|
|
42
41
|
"eslint-plugin-import": "^2.25.2",
|
|
43
|
-
"eslint-plugin-jest": "^
|
|
42
|
+
"eslint-plugin-jest": "^26.0.0",
|
|
44
43
|
"eslint-plugin-no-floating-promise": "^1.0.2",
|
|
45
44
|
"eslint-plugin-node": "^11.1.0",
|
|
46
45
|
"eslint-plugin-prettier": "^4.0.0",
|
|
47
|
-
"eslint-plugin-unused-imports": "^
|
|
48
|
-
"
|
|
46
|
+
"eslint-plugin-unused-imports": "^2.0.0",
|
|
47
|
+
"is-ci": "^3.0.1",
|
|
48
|
+
"jest": "^27.5.1",
|
|
49
49
|
"jest-environment-node": "^27.2.0",
|
|
50
|
-
"jest-extended": "^
|
|
51
|
-
"jest-html-reporters": "^3.0.
|
|
50
|
+
"jest-extended": "^2.0.0",
|
|
51
|
+
"jest-html-reporters": "^3.0.5",
|
|
52
52
|
"jest-mock-extended": "^2.0.4",
|
|
53
53
|
"jest-summary-reporter": "^0.0.2",
|
|
54
54
|
"prettier": "^2.4.1",
|
|
55
55
|
"ts-jest": "^27.1.3",
|
|
56
56
|
"ts-node": "^10.4.0",
|
|
57
57
|
"typescript": "^4.5.4"
|
|
58
|
-
}
|
|
58
|
+
},
|
|
59
|
+
"packageManager": "yarn@3.2.0"
|
|
59
60
|
}
|
package/lib/utilities.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
import { TimeUnit, toMilliseconds } from './timeunit';
|
|
2
|
-
|
|
3
|
-
class TimeoutError extends Error {
|
|
4
|
-
constructor(message?: string) {
|
|
5
|
-
super(message || 'Timeout');
|
|
6
|
-
}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Zzzz...
|
|
11
|
-
*
|
|
12
|
-
* @param time time to sleep
|
|
13
|
-
* @param units the units on time
|
|
14
|
-
* @returns a promise that resolves when the specified time has elapsed.
|
|
15
|
-
*/
|
|
16
|
-
function sleep(time: number, units?: TimeUnit): Promise<void> {
|
|
17
|
-
return new Promise(resolve => {
|
|
18
|
-
setTimeout(resolve, toMilliseconds(time, units));
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Delays the execution of the specified action and returns its value.
|
|
24
|
-
*
|
|
25
|
-
* @param action a function to execute with delay
|
|
26
|
-
* @param time time to sleep
|
|
27
|
-
* @param units the units on time
|
|
28
|
-
* @returns a promise that resolves when the specified time has elapsed.
|
|
29
|
-
*/
|
|
30
|
-
function delay<T>(action: () => T | Promise<T>, time: number, units?: TimeUnit): Promise<T> {
|
|
31
|
-
const delayMs = toMilliseconds(time, units);
|
|
32
|
-
return new Promise((resolve, reject) => {
|
|
33
|
-
const timer = setTimeout(() => Promise.resolve(action()).then(resolve, reject), delayMs);
|
|
34
|
-
process.on('beforeExit', () => {
|
|
35
|
-
clearTimeout(timer);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Return a function that returns the elapsed time relative to this call.
|
|
42
|
-
* @returns a function
|
|
43
|
-
*/
|
|
44
|
-
function stopwatch(): (units?: TimeUnit) => number {
|
|
45
|
-
const startTime = Date.now();
|
|
46
|
-
|
|
47
|
-
return (units?: TimeUnit) => {
|
|
48
|
-
return (Date.now() - startTime) / (units || TimeUnit.Milliseconds);
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Awaits a specified condition to evaluate to true with or without a timeout.
|
|
54
|
-
*
|
|
55
|
-
* @param condition the condition to wait for
|
|
56
|
-
* @param opts options that control evaluation intervals and timeout
|
|
57
|
-
* @returns a promise that resolves when the condition becomes true, or rejects when a set timeout is crossed.
|
|
58
|
-
*/
|
|
59
|
-
async function until(
|
|
60
|
-
condition: () => boolean,
|
|
61
|
-
opts?: { interval?: number; timeout: number; units?: TimeUnit }
|
|
62
|
-
): Promise<void> {
|
|
63
|
-
const defaultInterval = 50;
|
|
64
|
-
const deadline = opts ? Date.now() + toMilliseconds(opts.timeout, opts.units) : Number.MAX_VALUE;
|
|
65
|
-
const interval = opts?.interval ? toMilliseconds(opts.interval, opts.units) : defaultInterval;
|
|
66
|
-
|
|
67
|
-
return new Promise<void>((resolve, reject) => {
|
|
68
|
-
const handle = setInterval(() => {
|
|
69
|
-
if (Date.now() > deadline) {
|
|
70
|
-
clearInterval(handle);
|
|
71
|
-
reject(new TimeoutError());
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
try {
|
|
75
|
-
if (condition()) {
|
|
76
|
-
clearInterval(handle);
|
|
77
|
-
resolve();
|
|
78
|
-
}
|
|
79
|
-
} catch (e) {
|
|
80
|
-
clearInterval(handle);
|
|
81
|
-
reject(e);
|
|
82
|
-
}
|
|
83
|
-
}, interval);
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Alias to `until`
|
|
89
|
-
*/
|
|
90
|
-
const eventually = until;
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Executes an action with a specified timeout. If the action times out, rejects with TimeoutError.
|
|
94
|
-
*
|
|
95
|
-
* @param action an action to execute with timeout
|
|
96
|
-
* @param timeout the timeout to set for the action
|
|
97
|
-
* @param units the time units
|
|
98
|
-
* @returns the action result
|
|
99
|
-
*/
|
|
100
|
-
async function withTimeout<T>(action: () => T | Promise<T>, timeout: number, units?: TimeUnit): Promise<T> {
|
|
101
|
-
const promisedAction = new Promise<T>((resolve, reject) => {
|
|
102
|
-
try {
|
|
103
|
-
resolve(action());
|
|
104
|
-
} catch (e) {
|
|
105
|
-
reject(e);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
const race = new Promise<T>((resolve, reject) => {
|
|
110
|
-
const timer = setTimeout(() => {
|
|
111
|
-
reject(new TimeoutError());
|
|
112
|
-
}, toMilliseconds(timeout, units));
|
|
113
|
-
|
|
114
|
-
return Promise.resolve(promisedAction).then(
|
|
115
|
-
r => {
|
|
116
|
-
clearTimeout(timer);
|
|
117
|
-
resolve(r);
|
|
118
|
-
},
|
|
119
|
-
err => {
|
|
120
|
-
clearTimeout(timer);
|
|
121
|
-
reject(err);
|
|
122
|
-
}
|
|
123
|
-
);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
return race;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export { withTimeout, sleep, delay, stopwatch, until, eventually };
|