-
-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathasync.js
119 lines (108 loc) · 2.61 KB
/
async.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
'use strict';
const { Error } = require('./error.js');
const toBool = [() => true, () => false];
const timeout = (msec, signal = null) =>
new Promise((resolve, reject) => {
const timer = setTimeout(() => {
reject(new Error(`Timeout of ${msec}ms reached`, 'ETIMEOUT'));
}, msec);
if (!signal) return;
signal.addEventListener('abort', () => {
clearTimeout(timer);
reject(new Error('Timeout aborted'));
});
});
const delay = (msec, signal = null) =>
new Promise((resolve, reject) => {
const timer = setTimeout(resolve, msec);
if (!signal) return;
signal.addEventListener('abort', () => {
clearTimeout(timer);
reject(new Error('Delay aborted'));
});
});
const timeoutify = (promise, msec) =>
new Promise((resolve, reject) => {
let timer = setTimeout(() => {
timer = null;
reject(new Error(`Timeout of ${msec}ms reached`, 'ETIMEOUT'));
}, msec);
promise.then(
(result) => {
if (!timer) return;
clearTimeout(timer);
resolve(result);
},
(error) => {
if (!timer) return;
clearTimeout(timer);
reject(error);
},
);
});
const throttle = (fn, interval, ...presetArgs) => {
if (typeof interval !== 'number' || interval < 0) {
throw new Error('Interval must be greater then 0');
}
let lastTime = 0;
return (...args) => {
const now = Date.now();
if (now - lastTime < interval) return;
try {
fn(...presetArgs, ...args);
} finally {
lastTime = now;
}
};
};
const debounce = (fn, delay, ...args) => {
let timer = null;
return () => {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn(...args);
timer = null;
}, delay);
};
};
const callbackify =
(asyncFn) =>
(...args) => {
const callback = args.pop();
if (typeof callback !== 'function' || callback.length !== 2) {
throw new Error('Last argument should be a function with 2 parameters');
}
asyncFn(...args)
.then((res) => callback(null, res))
.catch((err) => callback(err));
};
const asyncify =
(fn) =>
(...args) => {
const callback = args.pop();
setTimeout(() => {
try {
const result = fn(...args);
callback(null, result);
} catch (error) {
callback(error);
}
}, 0);
};
const promisify =
(fn) =>
(...args) =>
new Promise((resolve, reject) =>
fn(...args, (err, data) => (err ? reject(err) : resolve(data))),
);
module.exports = {
toBool,
timeout,
delay,
timeoutify,
throttle,
debounce,
callbackify,
asyncify,
promisify,
};