本文最后更新于:2023年3月19日 晚上
                
              
            
            
              实现重试函数,Promiseify
实现一个方法 useRetryable,当调用 retryableFn 时,它的调用方式要与原始函数(即 fn)保持一致。
同时还具备重试功能:
- 如果 n 次内执行失败,进行重试;
- 一旦执行成功,就不再执行多余的次数了;
- 如果 n 次全部失败,抛出最后一次的异常。
| 12
 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 并立即执行,不是的话抛出错误。
解答
| 12
 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);
 
 |