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

如何配置API路由实现第三方API失败时返回本地服务器文件

实现方案

你现有代码的降级逻辑不生效,核心原因有两点:

  • node-fetch 只有网络层面故障(断网、域名解析失败、请求超时等)才会抛出异常,第三方接口返回400、500这类HTTP错误状态时,不会进入catch块,原有err === 400的判断永远无法触发
  • 异常捕获范围不全,没有覆盖响应状态异常、JSON解析失败、数据处理报错等场景

可按如下逻辑调整:

  • 提前加载本地兜底数据,避免每次请求重复读取文件产生额外IO
  • 请求第三方接口后先校验响应状态,非2xx状态直接触发兜底
  • 所有第三方接口请求、解析、处理环节的异常统一捕获,触发时返回本地数据
  • 已经设置Content-Type: application/json的前提下,直接给res.send传JS对象即可,框架会自动完成JSON序列化,不需要手动调用JSON.stringify

修正后的代码如下:

// 提前加载本地兜底JSON数据,按需替换为实际的本地文件读取逻辑
import localData from './local-fallback-data.json' assert { type: 'json' };

routes.get("/data", async (req: Request, res: Response, next: NextFunction) => {
  res.set({
    "Cache-Control": "no-store",
    "Content-Type": "application/json"
  });

  try {
    // 可选:添加超时控制,避免第三方接口长时间无响应阻塞请求
    const controller = new AbortController();
    const timer = setTimeout(() => controller.abort(), 5000);
    const apiResp = await fetch("https://api.blahblah.com/files", {
      signal: controller.signal
    });
    clearTimeout(timer);

    // 校验响应状态,非2xx状态直接抛出错误走兜底
    if (!apiResp.ok) {
      throw new Error(`API request error, status: ${apiResp.status}`);
    }

    const rawData = await apiResp.json();
    const formatData = rawData.filter((item: { fork: boolean }) => item.fork === false);

    res.send(formatData);
  } catch (err) {
    // 第三方接口全链路异常都走兜底,返回本地数据
    console.error("Third-party API request failed, return local fallback data:", err);
    res.send(localData);

    // 若有需要区分错误类型,可在此判断错误属性,非接口类错误传给全局错误中间件
    // 例如:if (isSystemError(err)) next(err)
  }
});

补充说明

  • 如果本地数据需要动态更新,可以给本地数据加缓存过期逻辑,定时重新读取文件即可
  • 如果需要针对特定HTTP状态码(比如400、503)做特殊处理,可在apiResp.ok判断分支里单独处理状态码
  • 若使用的node-fetch版本不支持AbortController,可替换为对应版本的超时实现方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 22:36:20