进阶Axios:从入门到实践,构建高效HTTP请求

1. Axios 概述

Axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js。它具有以下特点:

  • 支持浏览器和 Node.js 环境
  • 支持 Promise API
  • 可以拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 自动转换 JSON 数据

2. Axios 的基本使用

发送 GET 请求

axios.get('https://api.example.com/data')
  .then(response => {
    console.log(response.data);
  })
  .catch(error => {
    console.error(error);
  });

发送 POST 请求

axios.post('https://api.example.com/submit', {
  key: 'value'
})
  .then(response => {
    console.log(response.data);
  })
  .catch(error => {
    console.error(error);
  });

3. Axios 配置选项

你可以通过配置对象来调整请求的行为:

axios({
  method: 'post',
  url: 'https://api.example.com/submit',
  data: {
    key: 'value'
  },
  headers: {
    'Content-Type': 'application/json'
  }
})
.then(response => {
  console.log(response.data);
})
.catch(error => {
  console.error(error);
});

4. 创建 Axios 实例

可以创建预配置的 Axios 实例:

const instance = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 1000,
  headers: {'X-Custom-Header': 'foobar'}
});

5. 请求和响应拦截器

请求拦截器

axios.interceptors.request.use(
  function(config) {
    // 在发送请求之前做一些事情
    return config;
  },
  function(error) {
    // 处理请求错误
    return Promise.reject(error);
  }
);

响应拦截器

axios.interceptors.response.use(
  function(response) {
    // 对响应数据做点什么
    return response;
  },
  function(error) {
    // 对响应错误做点什么
    return Promise.reject(error);
  }
);

6. 错误处理

当使用 Axios 发送请求时,如果请求失败,Promise 将会被 reject,并且可以在 .catch() 块中捕获这个错误。下面是一个具体的示例:

axios.get('https://api.example.com/data')
  .then(response => {
    console.log('Data received:', response.data);
  })
  .catch(error => {
    console.error('An error occurred:', error);

    // 你可以检查错误的不同属性来确定错误的类型
    if (error.response) {
      // 请求已发出,服务器也响应了状态码,但状态码不在 2xx 范围内
      console.log('Server responded with a status of:', error.response.status);
      console.log('Response data:', error.response.data);
    } else if (error.request) {
      // 请求已发出,但没有收到响应
      console.log('No response received:', error.request);
    } else {
      // 设置请求时发生了错误
      console.log('Error setting up the request:', error.message);
    }
    console.log('Error config:', error.config);
  });

在这个示例中,我们向 'https://api.example.com/data' 发送了一个 GET 请求。如果请求成功,我们将接收到服务器返回的数据;但如果请求失败,.catch() 块将被触发,你可以在其中处理错误。

错误对象 error 包含了许多有用的信息,比如:

  • error.response:包含服务器的响应,如果有的话。它是一个包含 datastatusheaders 属性的对象。
  • error.request:包含创建的 XMLHttpRequest 对象,如果请求已经发出并且没有收到响应的话。
  • error.message:描述错误的字符串。
  • error.config:包含发送请求时的配置信息。

通过检查这些属性,可以更准确地定位错误原因,并采取相应的措施。例如,如果服务器返回了一个 404 错误,可能需要检查请求的 URL 是否正确;如果是 500 内部服务器错误,可能需要联系服务器管理员或开发者查看服务器日志。

7. 取消请求

可以创建一个 CancelToken 并在需要时取消请求:

const source = axios.CancelToken.source();

axios.get('/user/12345', {
  cancelToken: source.token
}).catch(thrown => {
  if (axios.isCancel(thrown)) {
    console.log('Request canceled', thrown.message);
  } else {
    // handle error
  }
});

// 取消请求
source.cancel('Operation canceled by the user.');

8. 封装 Axios

封装 Axios 可以让代码更整洁,更容易管理。可以在一个模块中封装所有的请求方法:

import axios from 'axios';

const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 1000,
});

// 封装 GET 请求
const get = (url, params) => apiClient.get(url, { params }).then(res => res.data);

// 封装 POST 请求
const post = (url, data) => apiClient.post(url, data).then(res => res.data);

// 封装 PUT 请求
const put = (url, data) => apiClient.put(url, data).then(res => res.data);

// 封装 DELETE 请求
const del = url => apiClient.delete(url).then(res => res.data);

// 封装 PATCH 请求
const patch = (url, data) => apiClient.patch(url, data).then(res => res.data);

// 导出这些方法
export { get, post, put, del, patch };

9. 高级用法

高级请求通常涉及更复杂的场景,例如处理大量并发请求、错误重试、请求取消、请求和响应的转换、自定义请求和响应拦截器等。下面我将通过一些具体的例子来展示这些高级用法。

1. 并发请求

当需要同时发送多个请求并等待所有请求完成时,可以使用 Promise.all 或者 axios.all 方法:

axios.all([
  axios.get('https://api.example.com/users'),
  axios.get('https://api.example.com/posts')
])
.then(axios.spread((usersResponse, postsResponse) => {
  console.log(usersResponse.data);
  console.log(postsResponse.data);
}))
.catch(errors => {
  console.error(errors);
});

2. 错误重试

在某些情况下,可能需要在请求失败后自动重试。这可以通过使用中间件或自定义拦截器来实现:

const retryInterceptor = axios.interceptors.response.use(
  response => response,
  async error => {
    const originalRequest = error.config;

    if (error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;

      try {
        const response = await axios.post('/auth/token');
        const token = response.data.token;
        originalRequest.headers['Authorization'] = `Bearer ${token}`;

        return axios(originalRequest);
      } catch (_error) {
        return Promise.reject(_error);
      }
    }

    return Promise.reject(error);
  }
);

3. 请求取消

在某些情况下,可能需要在请求发送后取消它。这可以通过 CancelToken 来实现:

const source = axios.CancelToken.source();

axios.get('/user/12345', {
  cancelToken: source.token
})
.then(response => {
  console.log(response.data);
})
.catch(throwError => {
  if (axios.isCancel(throwError)) {
    console.log('Request canceled', throwError.message);
  } else {
    console.error('A request failed:', throwError);
  }
});

// 后面的某个时刻,取消请求
source.cancel('Operation canceled by the user.');

4. 请求和响应转换

可能需要在发送请求或接收到响应之前转换数据,例如序列化或反序列化数据:

axios({
  url: '/foo',
  method: 'post',
  data: { bar: 'baz' },
  transformRequest: [function(data) {
    // 将请求数据转换成字符串
    return JSON.stringify({ ...data });
  }],
  transformResponse: [function(data) {
    // 将响应数据转换成 JSON 对象
    return JSON.parse(data);
  }]
})
.then(response => {
  console.log(response.data);
});

5. 自定义请求和响应拦截器

拦截器允许在请求被发送或响应被处理之前修改它们:

axios.interceptors.request.use(request => {
  // 在请求发送之前做一些事情
  console.log('Sending request:', request);
  return request;
}, error => {
  // 处理请求错误
  return Promise.reject(error);
});

axios.interceptors.response.use(response => {
  // 在响应被传递给 then 前做一些事情
  console.log('Received response:', response);
  return response;
}, error => {
  // 处理响应错误
  return Promise.reject(error);
});

通过这些高级功能,可以根据不同的需求定制 Axios 的行为,以满足复杂的应用场景。在实际开发中,结合业务需求选择合适的策略是非常重要的。

10. 性能优化

使用缓存、优化请求头和压缩技术是提高网络请求效率和性能的重要手段。下面将针对这三点给出具体的示例。

1. 使用缓存机制

示例: 使用 axios-cache-adapter 库来缓存响应,减少不必要的网络请求。

首先,需要安装 axios-cache-adapter

npm install axios-cache-adapter

然后,在代码中使用它:

import axios from 'axios';
import CacheAdapter from 'axios-cache-adapter';

const cache = new CacheAdapter({
  maxAge: 60 * 1000, // 缓存有效期为1分钟
});

const cachedAxios = axios.create({
  adapter: cache.adapter,
});

// 发送请求,如果缓存中有数据则不会再次请求
cachedAxios.get('https://api.example.com/data')
  .then(response => {
    console.log('Data received:', response.data);
  })
  .catch(error => {
    console.error('An error occurred:', error);
  });

2. 优化请求头

示例: 仅在需要时发送特定的请求头,例如 If-None-MatchIf-Modified-Since,以利用 HTTP 的条件请求。

import axios from 'axios';

let lastModified;

axios.get('https://api.example.com/data', {
  headers: {
    'If-Modified-Since': lastModified,
  },
})
.then(response => {
  console.log('Data received:', response.data);
  lastModified = response.headers['last-modified'];
})
.catch(error => {
  if (error.response && error.response.status === 304) {
    console.log('Data has not been modified since the last request');
  } else {
    console.error('An error occurred:', error);
  }
});

在这个例子中,如果服务器的数据没有改变,它会返回一个 304 Not Modified 的状态码,客户端就可以使用缓存中的数据,而无需下载新的数据。

3. 使用压缩技术

示例: 通过设置 Accept-Encoding 请求头来请求压缩的数据。

import axios from 'axios';

axios.get('https://api.example.com/data', {
  headers: {
    'Accept-Encoding': 'gzip, deflate, br', // 支持 gzip, deflate 和 Brotli 压缩
  },
})
.then(response => {
  console.log('Data received:', response.data);
})
.catch(error => {
  console.error('An error occurred:', error);
});

服务器如果支持压缩,会根据请求头中的 Accept-Encoding 字段来选择合适的压缩算法对响应体进行压缩,从而减少传输数据的大小,加快响应速度。

通过实施这些策略,可以显著提升应用的性能,减少用户的等待时间,同时降低服务器的带宽消耗。

结语

通过以上讲解,应该对 Axios 有了较为全面的理解。实践是检验学习成果的最佳方式,尝试在项目中应用 Axios,并不断探索其更多高级功能,会逐渐成为 Axios 的高手。如果遇到具体问题,查阅官方文档或寻求社区帮助都是很好的解决途径。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容