|
1 | | -const { isNumber } = require('./utilities') |
2 | | - |
3 | 1 | const createLinear = function (constants = {}) { |
4 | 2 | const { m = 1, b = 0 } = constants |
5 | 3 |
|
@@ -27,49 +25,43 @@ const createExponential = function (constants = {}, m = 1) { |
27 | 25 | module.exports.createExponential = createExponential |
28 | 26 |
|
29 | 27 | /** |
30 | | - * @param {Function} |
31 | | - * @param {Function|Number} |
32 | | - * @param {Number} |
33 | | - * @param {Function} |
| 28 | + * Wraps an `async` function for async retries as per the logic given in `curve`. |
| 29 | + * Curve is expected to be a callback which will be called at each failed |
| 30 | + * iteration with `err` (the error thrown by the wrapped function) and `count` |
| 31 | + * which is the count of total attempts to `resolve` - it should either throw |
| 32 | + * (should no more retries be required) or return an integer dictating the |
| 33 | + * number of milliseconds to sleep before re-attempting resolution. |
| 34 | + * |
| 35 | + * @param {Function} fn |
| 36 | + * @param {Function|Object} curve |
34 | 37 | * @returns {Function} |
35 | 38 | */ |
36 | | -const createRetrierFn = function (fn, curve = 2, limit = 2, shouldRetry = undefined) { |
37 | | - if (isNumber(curve)) { |
38 | | - limit = curve |
39 | | - curve = zero |
| 39 | +const createRetrierFn = function (fn, curve) { |
| 40 | + if (!curve) { |
| 41 | + curve = function (err, count) { |
| 42 | + if (count > 1) throw err |
| 43 | + return 0 |
| 44 | + } |
40 | 45 | } |
41 | 46 |
|
42 | | - return function () { |
43 | | - const args = Array.prototype.slice.call(arguments) |
44 | | - |
45 | | - return new Promise(function (resolve, reject) { |
46 | | - (function recurse(attempt) { |
47 | | - function retry(error) { |
48 | | - const errorCount = attempt + 1 |
49 | | - |
50 | | - if (limit && errorCount >= limit) return reject(error) |
51 | | - |
52 | | - if (shouldRetry && !shouldRetry(error)) return reject(error) |
53 | | - |
54 | | - return recurse(errorCount) |
| 47 | + return function (...args) { |
| 48 | + let attempt = 0 |
| 49 | + |
| 50 | + const recurse = function (resolve, reject) { |
| 51 | + return fn(...args).then(resolve).catch(function (err) { |
| 52 | + let timeout = curve(err, ++attempt) |
| 53 | + if (timeout < 0) return reject(err) |
| 54 | + try { |
| 55 | + if (err <= 0) return recurse(resolve, reject) |
| 56 | + return setTimeout(recurse, timeout, resolve, reject) |
| 57 | + } catch (_err) { |
| 58 | + return reject(_err) |
55 | 59 | } |
| 60 | + }) |
| 61 | + } |
56 | 62 |
|
57 | | - setTimeout(function () { |
58 | | - try { |
59 | | - Promise |
60 | | - .resolve(fn.apply(null, args)) |
61 | | - .then(resolve) |
62 | | - .catch(function (asyncErr) { |
63 | | - return retry(asyncErr) |
64 | | - }) |
65 | | - } catch (syncErr) { |
66 | | - retry(syncErr) |
67 | | - } |
68 | | - }, curve(attempt)) |
69 | | - }(null, 0)) |
70 | | - }) |
| 63 | + return new Promise(recurse) |
71 | 64 | } |
72 | 65 | } |
73 | 66 |
|
74 | | -module.exports.retry = createRetrierFn |
75 | 67 | module.exports.createRetrierFn = createRetrierFn |
0 commit comments