javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > Axios封装与实战

从接口文档到前端调用之Axios封装与实战的完全流程

作者:二叉树果实

axios不是一种新技术,本质上也是对原生XHR的封装,只不过它是基于Promise的,是Promise的实现版本,符合最新的ES规范,这篇文章主要介绍了从接口文档到前端调用之Axios封装与实战的相关资料,需要的朋友可以参考下

1.如何看接口文档?

在一个接口文档中,有很多的请求类型(也叫 HTTP 方法 / 动作)

这里仅以 GET 和 POST 做讲解,其他的请求类型,都类似

1.1 GET

注意:GET 跟 URL 息息相关

来看一个具体的例子:

首先,接口都会有一个 baseUrl,作为获取数据的地址,使用不同的接口时,又会有不同的路径,比如这个就是/my/cate/info

第一部分:请求参数(Request Parameters)

Query 参数和 Header 参数

Query 参数和 Header 参数

query 跟 url 息息相关

header 跟身份验证相关,就是说,想让这个请求发送给接口,必须满足一些条件,header 就像一把钥匙

文档中这两部分都必须传对,否则接口要么报错,要么不给你数据。

  1. Query 参数
  1. Header 参数

Authorization:英语中授权的意思

第二部分:响应(Response)

{
  "code": 0,
  "message": "获取文章分类成功!",
  "data": {
    "id": 1070,
    "cate_name": "科技",
    "cate_alias": "keji"
  }
}

这部分就是告诉你:调用成功以后,后台会返回什么样的数据结构,你前端代码里就可以用这些字段来展示页面。

1.2 POST

看如下例子:返回响应部分不做介绍,POST 请求方法没有 Query 参数,而是 Body 参数

Body 参数(请求体)

这是 POST 接口的重点,和 GET 很不同:

在文档里,它定义了两个字段:

  1. cate_name (string)
    • 文章分类名字,比如“娱乐”、“科技”。
    • 必填,长度限制:1–10 个非空字符。
  2. cate_alias (string)
    • 文章分类别名,比如“yule”、“keji”。
    • 必填,长度限制:1–15 个大小写字母和数字组合。

示例 JSON

{
  "cate_name": "娱乐",
  "cate_alias": "yule"
}

为什么 GET 没有 Body,而 POST 要用 Body?

GET:只是获取数据,不修改,所以参数少,放 URL 上即可。

POST:要创建一条新数据,通常包含多个字段(标题、别名、内容……),如果写在 URL 会很长很乱,所以必须放到 Body 里,结构化成 JSON。

2.为什么要封装请求拦截器和响应拦截器?如何封装?

简单来说,实际开发过程中,不能每一次都手动的在请求头中加入授权的 token,而请求拦截器,会拦截请求将每个授权的 token 加入到本次的请求头当中.

统一封装 axios 请求模板:

官方文档:https://www.axios-http.cn/docs/interceptors

import axios from 'axios'

const baseURL = 'http://big-event-vue-api-t.itheima.net'

const instance = axios.create({
  // 1. 基础地址,超时时间(配置项)
})

//请求拦截器
instance.interceptors.request.use(
  (config) => {
    // 2. 携带token,将 token 值赋给请求头
    return config
  },
  (err) => Promise.reject(err)
)

//响应拦截器
instance.interceptors.response.use(
//http 返回 200 成功
  (res) => {  
    // 3. 正确拿到了业务数据
    
    // 4. 业务逻辑错误,例如限制密码字母大写
    return res
  },
  (err) => {
    // 5. 处理http 返回401错误
    return Promise.reject(err)
  }
)

export default instance

2.1 封装axios实例

(1)统一配置

timeout:请求超过 x 毫秒还没响应,就自动报错,进入 .catch()

请求中几乎所有接口都需要,而且不会频繁变化 的东西,适合直接写在 axios.create()headers 里,所以 token 不应该写在这里,token 应写在拦截器中

(2)更好的可维护性

(3)添加请求/响应拦截器

(4)支持多实例

有些项目里:

封装axios实例代码如下:

import axios from 'axios'
const baseURL = 'http://big-event-vue-api-t.itheima.net'

const instance = axios.create({
  baseURL,
  timeout: 100000
})

2.2 封装拦截器

官方文档中的拦截器

// 添加请求拦截器
axios.interceptors.request.use(function (config) {
    // 在发送请求之前做些什么
    return config;
  }, function (error) {
    // 对请求错误做些什么
    return Promise.reject(error);
  });

// 添加响应拦截器
axios.interceptors.response.use(function (response) {
    // 2xx 范围内的状态码都会触发该函数。
    // 对响应数据做点什么
    return response;
  }, function (error) {
    // 超出 2xx 范围的状态码都会触发该函数。
    // 对响应错误做点什么
    return Promise.reject(error);
  });

分析:

request 拦截器的代码是一样的,关键在于拿到的对象不一样,一个是 config,一个是 response

注意:

2.3 拦截器实践

请求拦截器:使用 pinia 存储的 token,将 token 值赋给请求头

instance.interceptors.request.use(
  (config) => {
    const userStore = useUserStore()
    if (userStore.token) {
      config.headers.Authorization = userStore.token
    }
    return config
  },
  (err) => Promise.reject(err)

响应拦截器:

instance.interceptors.response.use(
  (res) => {
    if (res.data.code === 0) {
      return res
    }
    ElMessage({ message: res.data.message || '服务异常', type: 'error' })
    return Promise.reject(res.data)
  },
  (err) => {
    ElMessage({ message: err.response.data.message || '服务异常', type: 'error' })
    console.log(err)
    if (err.response?.status === 401) {
      router.push('/login')
    }
    return Promise.reject(err)
  }
)

导出

export default instance
export { baseURL }

3.如何在实际的项目中使用axios

3.1 GET

无需请求参数的 GET

在 src/api 下创建自定义的 js 文件,如 article.js.存放跟文章相关的 api

src/api/article.js

import request from '@/utils/request'
//获取文章分类
export const artGetChannelsService=()=>request.get('/my/cate/list')

需要请求参数的 GET

API 封装:

// 获取文章分类详情 ?id=xxx
export const artGetChannelDetailService = (id) => {
  return request.get('/my/cate/info', {
    params: { id }          // => /my/cate/info?id=1284
  })
}

为什么写 params 呢?

因为能拼到 url 后面

在 .vue 里使用:

import { artGetChannelDetailService } from '@/api/article'

const id = route.query.id   // 比如路由里带着 ?id=1284
await artGetChannelDetailService(id)

3.2 POST

以这个为例:

import request from '@/utils/request'
//添加文章分类
export const artAddChannelService=(data)=>request.post('/my/cate/add',data)

3.3. DELETE

Delete 也是需要一个请求参数,写法跟带参数的 GET 一样

API 封装:

// 删除文章分类
export const artDelChannelService = (id) =>
  request.delete('/my/cate/del', {
    params: { id }
  })

3.4 PUT

put 跟 post 写法一样,除了 request 方法是 put

API 封装:

export const artEditChannelService =(data)=> request.put('/my/cate/info',data)

在实际写法中,也可以不用形参 data,直接传对象,比如

//更新个人信息
export const userUpdateInfoService = ({ id, nickname, email }) =>
  request.put('/my/userinfo', { id, nickname, email })

3.5 PATCH

API 封装:

跟 post 一样

//上传头像
export const userUploadAvatarService = (avatar) => request.patch('/my/update/avatar', { avatar })

总结 

到此这篇关于从接口文档到前端调用之Axios封装与实战的文章就介绍到这了,更多相关Axios封装与实战内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文