在进行 JavaScript 编程时,特别是在处理网络请求或异步操作时,出现错误或失败的情况时常发生。为了提高系统的健壮性,我们常常需要为异步操作实现一个“失败重传”的机制,自动尝试重试失败的操作,直到成功或达到最大重试次数。
今天,我们将一起解析一个面试题,帮助大家更好地理解如何实现失败重传机制。
问题分析
我们需要实现一个 retry
函数,该函数接受两个参数:
fn
: 一个返回Promise
的异步函数。maxTimes
: 最大重试次数,默认为 3 次,也可自行设置。
我们将通过这个 retry
函数执行异步操作 fn
,如果异步操作失败,就会根据最大重试次数来决定是否再次尝试。
代码实现
// retry 函数实现,支持失败重传机制
function retry(fn, maxTimes = 3) {
let count = 1; // 初始化重试次数为 1
return new Promise((resolve, reject) => {
const repeat = () => {
// 执行传入的异步函数 fn
fn()
.then((res) => {
resolve(res); // 如果异步操作成功,返回结果
})
.catch((err) => {
count++; // 如果失败,增加重试次数
if (count > maxTimes) {
reject(err); // 如果重试次数超过最大值,返回错误
} else {
repeat(); // 否则递归调用重新执行 repeat 进行重试
}
});
};
repeat(); // 启动第一次执行
});
}
// 模拟一个可能失败的异步操作
function test() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const time = Math.floor(Math.random() * 10); // 生成 0 到 9 之间的随机数
console.log(time); // 输出随机数,帮助我们调试
if (time < 8) {
reject('失败'); // 随机数小于 8,认为操作失败
} else {
resolve('成功'); // 随机数大于等于 8,认为操作成功
}
}, 500); // 模拟 500ms 的延迟
});
}
// 调用 retry 函数,最多重试 3 次
retry(test, 3)
.then(res => {
console.log(res); // 如果重试成功,输出结果
})
.catch(err => {
console.log(err); // 如果达到最大重试次数仍然失败,输出错误
});
代码解释
-
count
:该变量用来记录当前是第几次尝试执行异步操作。初始值为 1。 -
repeat
:这是一个递归函数,每次调用repeat
都会尝试执行一次异步操作fn
。如果操作成功,则通过resolve
返回结果;如果操作失败,则增加count
计数,并根据count
是否超过最大重试次数来决定是否再次重试。 -
重试逻辑:当
fn
执行失败时,catch
语句会捕获错误,增加重试次数。如果重试次数没有超过最大次数,就会递归调用repeat
继续重试;如果超过最大次数,则通过reject
返回错误信息。
总结
通过实现 retry
函数,我们能够在异步操作失败时自动重试。这种失败重传机制在实际开发中非常有用,特别是在处理网络请求、数据库操作等可能由于临时网络问题或其他原因而失败的场景。
关键点:
- 重试次数:我们可以通过
maxTimes
来控制最大重试次数。 - 递归重试:通过递归调用
repeat
,我们实现了重试机制。 - Promise 处理:我们使用
Promise
的.then()
和.catch()
来处理异步操作的成功与失败。