You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Axios请求错误在try/catch+await下仍出现未处理异常?

问题描述

我用TypeScript开发一款homebridge插件,使用Axios处理网络请求。插件会先登录本地网络中的服务器,之后按固定间隔轮询获取服务器状态信息;当会话过期时,服务器返回302错误并重定向到登录页,因此插件禁用了重定向,监测30x错误以触发重新登录、更新会话后重试请求。所有对网络请求函数的调用都包裹在try { await... } catch { }块中,但仍有部分错误绕过错误处理机制,传播到主事件循环导致插件崩溃。

相关代码

类构造函数

// [...]
this.client = axios.create({
  baseURL: this.httpPrefix + this.IPAddress,
  timeout: 10000,
  maxRedirects: 0,
  method: "post",
  headers: {
    'content-type': 'application/x-www-form-urlencoded'
  }
});
// [...]

轮询函数

[...]
try {
  const response = await this.makeRequest('user/seq.xml', {'sess': this.sessionID});
  // [...]
} catch (error) { throw(error); }

请求处理辅助函数

private async makeRequest(address: string, payload = {}) {
  try {
    return await this.client({
      url: address,
      data: payload
    });
  } catch (error) {
    if (axios.isAxiosError(error)) {
      const response = error.response;
      if (response == undefined) throw error;
      if (response.status >= 300 && response.status < 400) {
        await this.login();
        payload['sess'] = this.sessionID;
        const response = await this.client({
          url: address,
          data: payload
        });
        return response;
      } else throw(error);
    } else throw (error);
  }
}

轮询调度函数

async updateAccessories() {
  // [...]
  try {
    await this.securitySystem.poll();
    // [...]
  } catch (error) {
    this.log.error((<Error>error).message);
    await delay(retryDelayDuration);
  }

  setTimeout(this.updateAccessories.bind(this), this.pollTimer);
}

delay辅助函数

export function delay(milliseconds: number) {
    return new Promise(resolve => setTimeout(resolve, milliseconds));
}

错误现象

间歇性出现未处理错误,导致插件崩溃:

AxiosError: Request failed with status code 302
    at settle (/usr/lib/node_modules/homebridge-caddx-interlogix/node_modules/axios/lib/core/settle.js:19:12)
    at IncomingMessage.handleStreamEnd (/usr/lib/node_modules/homebridge-caddx-interlogix/node_modules/axios/lib/adapters/http.js:495:11)
    at IncomingMessage.emit (node:events:525:35)
    at endReadableNT (node:internal/streams/readable:1358:12)
    at processTicksAndRejections (node:internal/process/task_queues:83:21)

解决思路

1. 修复makeRequest的重试错误处理

当前makeRequest在捕获30x错误后,重新调用this.client时未包裹错误处理,若重试请求再次失败(如登录后会话仍无效、网络波动),错误会直接逃逸。修改代码覆盖重试分支的错误捕获:

private async makeRequest(address: string, payload = {}) {
  try {
    return await this.client({
      url: address,
      data: payload
    });
  } catch (error) {
    if (axios.isAxiosError(error)) {
      const response = error.response;
      if (!response) {
        throw error;
      }
      if (response.status >= 300 && response.status < 400) {
        await this.login();
        payload['sess'] = this.sessionID;
        // 重试请求添加错误捕获
        try {
          return await this.client({
            url: address,
            data: payload
          });
        } catch (retryError) {
          throw retryError;
        }
      } else {
        throw error;
      }
    } else {
      throw error;
    }
  }
}

2. 移除轮询函数中不必要的错误重抛

轮询函数里捕获错误后直接throw(error),会让错误继续向上传播,增加逃逸风险。改为直接在内部处理错误:

// 修改轮询函数
try {
  const response = await this.makeRequest('user/seq.xml', {'sess': this.sessionID});
  // [...]
} catch (error) {
  this.log.error('轮询请求失败:', (error as Error).message);
  // 此处不再重抛错误,由上层updateAccessories统一处理
}

3. 确保updateAccessories的异步错误完全被捕获

用finally块确保无论请求成功或失败,都会触发下一次轮询,同时避免异步回调的错误逃逸:

async updateAccessories() {
  try {
    await this.securitySystem.poll();
    // [...]
  } catch (error) {
    this.log.error((<Error>error).message);
    await delay(retryDelayDuration);
  } finally {
    // 确保无论结果如何,都会启动下一次轮询
    setTimeout(() => this.updateAccessories(), this.pollTimer);
  }
}

4. 添加全局错误兜底监听

在插件初始化时添加全局未捕获错误监听,防止极端情况下的错误导致插件崩溃:

// 插件构造函数中
process.on('unhandledRejection', (reason) => {
  this.log.error('未处理的Promise拒绝:', reason);
  // 可在此添加会话重置等恢复逻辑
});

process.on('uncaughtException', (error) => {
  this.log.error('未捕获的异常:', error);
});

内容的提问来源于stack exchange,提问作者Flareman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 22:46:05