# 统一返回与错误格式

URL: https://caijiao.org/axios/wrapper/response-format
Source: docs/axios/wrapper/response-format.md
Description: 本章节讲解如何在 Axios 中统一处理接口返回格式和错误结构，包括成功响应的规范化封装、错误对象的标准化以及后端返回数据的统一解析方式，帮助你构建更稳定、可维护的网络层。

在团队开发中，接口返回格式如果不统一，前端代码容易出现大量冗余判断与重复处理。通过在 Axios 层统一封装返回数据与错误结构，可以让业务代码更加简洁。

## 1. 典型接口返回格式

后端接口通常返回以下格式的数据结构：

```json
{
  "code": 200,
  "message": "操作成功",
  "data": {
    "user": {
      "id": 1,
      "name": "张三"
    }
  }
}
````

我们可以根据后端规范定义 Axios 统一的返回模型。

## 2. 封装响应拦截器统一处理返回数据

在拦截器中只返回 `data.data`，并对 `code` 进行判断：

```js
import axios from 'axios';

const service = axios.create({
  baseURL: '/api',
  timeout: 10000
});

service.interceptors.response.use(
  (response) => {
    const res = response.data;
    if (res.code === 200) {
      return res.data;
    } else {
      console.error('请求错误：', res.message);
      return Promise.reject({
        code: res.code,
        message: res.message || '请求失败',
        raw: res
      });
    }
  },
  (error) => {
    return Promise.reject({
      code: error.response?.status || 500,
      message: error.message || '网络错误',
      raw: error
    });
  }
);

export default service;
```

这样业务层拿到的数据始终是处理好的 `data`，无需再判断 `code`。

## 3. 定义统一的响应与错误类型（TypeScript 推荐）

如果你的项目使用 TypeScript，可以定义标准类型：

```ts
export interface ApiResponse<T> {
  code: number;
  message: string;
  data: T;
}

export interface ApiError {
  code: number;
  message: string;
  raw?: any;
}
```

在拦截器中确保所有错误都转化为 `ApiError` 格式，方便全局捕获。

## 4. 封装统一的请求函数

通过包装 Axios 请求方法，统一返回 Promise：

```js
export function requestWrapper(promise) {
  return promise
    .then((data) => [data, null])
    .catch((error) => [null, error]);
}
```

使用时：

```js
const [user, err] = await requestWrapper(api.getUserInfo());
if (err) {
  console.error('请求失败：', err.message);
}
```

这种结构可以避免层层 try/catch，尤其适合在 Vue 或 React 的 async 逻辑中使用。

## 5. 在全局提示层统一处理错误

你可以结合全局 UI 提示组件（如 Element Plus 的 `ElMessage`）：

```js
import { ElMessage } from 'element-plus';

service.interceptors.response.use(
  (res) => {
    const data = res.data;
    if (data.code !== 200) {
      ElMessage.error(data.message || '请求失败');
      return Promise.reject(data);
    }
    return data.data;
  },
  (error) => {
    ElMessage.error(error.message || '网络错误');
    return Promise.reject(error);
  }
);
```

这样在所有 API 请求中都能自动弹出错误提示。

## 6. 最佳实践总结

* ✅ 所有接口统一使用 `{ code, message, data }` 结构
* ✅ 在响应拦截器中规范化 `data` 与 `error`
* ✅ 错误对象应包含 `code`、`message`、`raw` 三要素
* ✅ 使用全局 UI 层统一展示错误信息
* ✅ 使用 `requestWrapper` 函数减少 try/catch 嵌套
