使用promise封装一个retry
今天被问到:使用promise封装一个retry函数,如果一个请求失败,重试几次后也失败就抛出错误
以下为失败尝试,可以直接跳转到完整案例
如果您有更好的案例,欢迎分享
失败经历
我简单思考了一下,这里可以用递归,写出了如下代码
function retry (task, count) {
return new Promise((resolve, reject) => {
task.then(res => { // 未执行
resolve(res)
})
.catch(() => {
if (count > 0) {
return retry(task, count--) // 死循环
}
else {
reject('次数用完了')
}
})
})
}
写了一个测试用例,好家伙,直接崩了。。。
修改注释的错误后,我又上路了
function retry (task, count) {
return new Promise((resolve, reject) => {
task().then(res => {
resolve(res)
})
.catch(() => {
if (count > 0) {
return retry(task, count-1)
}
else {
reject('次数用完了')
}
})
})
}
这次算是能实现失败后重试了,但是,当次数用完后抛出了一个错误,程序不能继续执行了
可是我明明使用了.catch
捕获reject啊,这就令人费解了
报错嘛,大不了我try、catch
一下
那么try、catch
加在哪里呢?我想到使用async、await
时的一种场景
async function run() {
try {
await retry(task, 1)
}
catch (e) {
console.log(e)
}
console.log('done')
}
run()
我低估了异步的错误,这家伙成精了啊
于是我开始搜索如何解决promise的错误
都是清一色的.catch(e => {})
,我也是这么写的啊,怎么会没有用呢
我想问题应该在于我catch到了第一次调用,第一次失败并没有reject,而是递归调用了自身,生成了一个新的promise对象
于是我换了一个思路
function retry(task, count) {
console.log('还有' + count + '次')
return new Promise((resolve, reject) => {
task()
.then(res => {
resolve(res)
})
.catch(() => {
if (count > 0) {
retry(task, count - 1)
} else {
reject('次数用完了')
}
})
}).catch(e => console.log(e)) // 捕获当前promise的错误
}
这次确实成功捕获到了错误,但是我没法拿到错误,也没能继续执行下去
既然确定了是因为重试生成promise对象和之前的没有关联,那么,问题很简单就解决了
完整案例
经过几次失败,这个案例应该趋于成功了吧
function retry(task, count) {
console.log('还有' + count + '次')
return new Promise((resolve, reject) => {
task()
.then(res => {
resolve(res)
})
.catch(() => {
if (count > 0) {
resolve(retry(task, count - 1)) // 这里使用resolve
} else {
reject('次数用完了')
}
})
})
}
无个性不签名