本文最后更新于:2023年3月19日 晚上
实现重试函数,Promiseify
实现一个方法 useRetryable,当调用 retryableFn 时,它的调用方式要与原始函数(即 fn)保持一致。
同时还具备重试功能:
- 如果 n 次内执行失败,进行重试;
- 一旦执行成功,就不再执行多余的次数了;
- 如果 n 次全部失败,抛出最后一次的异常。
1 2 3 4 5 6 7 8 9 10 11 12 13
| function useRetryable(fn, time) {}
const retryableFn = useRetryable(fn, 3);
retryableFn();
|
思路
使用 Promiseify 的思想,返回一个 Promise,同时处理同步和异步方法:
- 使用 try-catch 捕捉同步方法的错误。
- 使用 res 存储执行方法的 return 值,判断是否属于 Promise。
- 是异步的方法,无法使用 try-catch 捕捉,使用 Promise 的 catch 进行错误处理
- 两个错误处理中,判断当 time 是否大于 1,是的话继续返回 useRetryable 并立即执行,不是的话抛出错误。
解答
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
| function useRetryable(fn, time) { return (...args) => new Promise(async (resolve, reject) => { try { const res = fn.apply(globalThis, args); if (res instanceof Promise) { res.catch((err) => { if (time > 1) useRetryable(fn, --time)(...args); else throw Error(err); }); } } catch (err) { if (time > 1) useRetryable(fn, --time)(...args); else throw Error(err); } }); }
const asyncfn = async (...args) => { const num = Math.round(Math.random() * 10); console.log(num); return new Promise((resolve, reject) => { if (num < 3) { console.log(args); resolve(num); } else { reject("error"); } }); };
const syncfn = (...args) => { const num = Math.round(Math.random() * 10); console.log(num); if (num < 3) { console.log(args); } else throw new Error("error"); };
const retryableFnAsync = useRetryable(asyncfn, 3); const retryableFnSync = useRetryable(syncfn, 3);
retryableFnAsync(222, 333, 444); retryableFnSync(222, 333, 444);
|