Promise的重试是指在使用Promise进行异步操作时,如果操作失败,可以进行一定次数的重试,以尝试解决问题并获得成功的结果。
在JavaScript中,可以通过编写一个retry函数来实现Promise的重试功能。我们就直入主题吧,上老王的retry版。
// 封装的promise重试, input 函数应返回promise(如api请求)
function lwRetry(input, options) {
const opt = Object.assign({
retries: 3, // 重试次数
leftRetries: options.retries ?? 3, // 剩余重试次数
onFailedAttempt: async () => {},
state: {} // 挂载自定义数据
}, options)
const attempt = async (opt) => {
return input().catch(async err => {
if (opt.leftRetries > 0) {
// onFailedAttempt 如果抛出错误或者返回失败的promise,就会终止重试
await opt.onFailedAttempt(err, opt);
console.log(
`总共可以尝试${ opt.retries }次,本次第${ opt.retries - opt.leftRetries + 1 }次尝试,还可以尝试${opt.leftRetries - 1}次`
);
opt.leftRetries--;
return attempt(opt); // 形成一个重试promise链,直到重试次数用完或者成功
} else {
throw err;
}
})
}
return attempt(opt);
}
跑个例子
const fakeRequest = async () => {
console.log('request...');
if (Math.random() >= 0.5) return 'success';
else throw new Error('Failed to fetch');
};
lwRetry(fakeRequest, {
retries: 3,
onFailedAttempt: async (error, opt) => {
console.log('err', error.message, opt);
}
}).then(res => {
console.log('成功了', res);
}).catch(err => {
console.log('失败了', err);
})
老王,这重试没有时间间隔好像不大行呀!!!
嗯,有点道理哈~
function lwRetry(input, options) {
const opt = Object.assign({
retries: 3, // 重试次数
leftRetries: options.retries ?? 3, // 剩余重试次数
onFailedAttempt: async () => {},
/* 加上重试时间间隔 */
intervalFn(opt) {},
state: {} // 挂载自定义数据
}, options)
const attempt = async (opt) => {
return input().catch(async err => {
if (opt.leftRetries > 0) {
// onFailedAttempt 如果抛出错误或者返回失败的promise,就会终止重试
await opt.onFailedAttempt(err, opt);
console.log(
`总共可以尝试${ opt.retries }次,本次第${ opt.retries - opt.leftRetries + 1 }次尝试,还可以尝试${opt.leftRetries - 1}次`
);
opt.leftRetries--;
const interval = opt.intervalFn(opt);
console.log('===>interval', interval);
// 生成重试间隔时间...
if (interval && typeof interval === 'number') {
return new Promise((resolve, reject) => {
setTimeout( () => resolve(attempt(opt)), interval)
})
}
return attempt(opt); // 形成一个重试promise链,直到重试次数用完或者成功
} else {
throw err;
}
})
}
return attempt(opt);
}
更多的大家可以自由发挥,推荐一个库吧:
p-retry看了这个老王才想着试着写一个水篇文章。
可以去npm 或 github 看看代码