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

在Express控制器中调用axios时如何正确返回响应状态码

问题核心原因

你遇到的状态码始终为200的问题,根源有两个:

  1. getAddressWithPostcode的catch块没有抛出错误,而是将错误信息包装成普通对象返回,导致该异步函数的Promise永远是resolved状态,永远走路由层的then分支,被硬设了200状态码
  2. Express中res.status()需要放在res.send()前调用,res.send()会直接结束响应,你原来写的res.send(data).status(200)里的status设置不会生效

现有写法的可优化点

你重构后的代码仍然存在几个隐患:

  • 拼接地址时的api-keey是笔误,会导致所有带门牌号的请求直接鉴权失败
  • 成功请求返回的是axios的响应体data,错误请求返回的是完整的response对象,数据结构不一致,若业务返回的data中恰好有status字段会触发逻辑异常
  • 把错误结果放到resolved分支处理,不符合Promise的设计逻辑,后续维护成本更高

最佳实践方案

1. 服务层只负责调用、不处理响应格式,错误直接抛出

const getAddressWithPostcode = async (params: Params) => {
  const { postCode, number } = params
  // 修复参数拼写笔误
  const addressUrl = `${URL}/${postCode}${number
    ? `/${number}?api-key=${API_KEY}`
    : `?api-key=${API_KEY}`}`
  const { data } = await axios.get(addressUrl)
  return data
}

这里不需要单独加try/catch,axios请求出错会自动抛出错误,进入Promise的rejected分支。

2. 路由层分别处理成功/错误分支,正确设置状态码

const findAddress = async (req: Request<Params>, res: Response, next: NextFunction) => {
  try {
    const data = await getAddressWithPostcode(req.params)
    // Express默认响应状态码为200,不需要额外设置
    res.send(data)
  } catch (e) {
    // 优先取第三方服务返回的状态码,兜底设为500
    const status = e.response?.status || 500
    res.status(status).send({
      service: 'Address service error',
      status,
      statusText: e.response?.statusText || 'Internal Server Error'
    })
  }
}

如果你的项目有全局错误处理中间件,也可以直接把错误传给next(e),在全局中间件统一做格式化返回,不用每个路由重复写错误逻辑:

// 全局错误处理中间件,放在所有路由之后注册
app.use((err, req, res, next) => {
  console.error(err)
  const status = err.response?.status || 500
  res.status(status).json({
    code: status,
    message: err.response?.statusText || err.message || '服务器内部错误'
  })
})

额外建议

如果需要区分是第三方服务错误还是你自己的服务错误,可以自定义错误类,抛出时带上错误类型,全局中间件根据错误类型返回不同的提示信息即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 00:36:01