面试题知多少?--失败重传

66 阅读3分钟

在进行 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); // 如果达到最大重试次数仍然失败,输出错误
  });

代码解释

  1. count:该变量用来记录当前是第几次尝试执行异步操作。初始值为 1。

  2. repeat:这是一个递归函数,每次调用 repeat 都会尝试执行一次异步操作 fn。如果操作成功,则通过 resolve 返回结果;如果操作失败,则增加 count 计数,并根据 count 是否超过最大重试次数来决定是否再次重试。

  3. 重试逻辑:当 fn 执行失败时,catch 语句会捕获错误,增加重试次数。如果重试次数没有超过最大次数,就会递归调用 repeat 继续重试;如果超过最大次数,则通过 reject 返回错误信息。

总结

通过实现 retry 函数,我们能够在异步操作失败时自动重试。这种失败重传机制在实际开发中非常有用,特别是在处理网络请求、数据库操作等可能由于临时网络问题或其他原因而失败的场景。

关键点:

  1. 重试次数:我们可以通过 maxTimes 来控制最大重试次数。
  2. 递归重试:通过递归调用 repeat,我们实现了重试机制。
  3. Promise 处理:我们使用 Promise.then().catch() 来处理异步操作的成功与失败。