/**
* 把任意一个函数,修饰生成一个带重试功能的新函数。
* 1、如果执行失败,进行重试;
* 2、如果执行成功,直接返回结果;
* 3、如果重试了 n 次依然失败,抛出最后一次的异常。
* 4、新函数的表现行为要尽可能与原函数保持一致
*
* @param {Function} fn
* @param {number} n 最大重试次数
* @return {Function} 带有重试功能的新函数
*/
//同步递归版:
function useRetryable(fn, times) {
return function retryableFn(...arg) {
try {
return fn(...arg);
} catch (error) {
if (--times === 0) throw error;
else return retryableFn(...arg);
}
};
}
// test code
// let count = 3;
// const testFunc = function () {
// if (count > 0) {
// count--;
// throw Error('this is an error');
// } else return 'yeah~~suukii';
// };
// const fn = useRetryable(testFunc, 4);
// console.log(fn());
//异步版本(递归):
function useRetryableAsync(fn, times) {
return function retryableFn(...arg) {
times--;
return fn(...arg)
.then(data => data)
.catch(error => {
if (times === 0) throw error;
// notes: 要把递归的结果 return 呀
else return retryableFn(...arg);
});
};
}
// test code
let count = 3;
const testFunc = function () {
return new Promise((res, rej) => {
setTimeout(() => {
count > 0 ? rej('this is an error') : res('yeah~~suukii');
count--;
}, 100);
});
};
const fn = useRetryableAsync(testFunc, 4);
fn()
.then(data => {
console.log(data);
})
.catch(err => {
console.log(err);
});
console