本文将简单讲述ajax请求封装,将以axios插件和fetch原生封装做代码演示。请求封装一般需要封装请求头,是否携带token,响应拦截器结构数据等等操作。

image.png

axios请求封装:

1、安装axios:yarn add axios(也可以npm i axios,其他工具大同小异)

2、导入axios

import axios from 'axios'

3、配置基地址和超时时间

const baseURL = 'http://localhost:3000'
const ins = axios.create({ //axios常规封装方式
    baseURL,
    timeout: 4000
})

4、配置请求拦截器(用于在请求头携带token)

ins.interceptors.request.use((config) => { //请求拦截器
    const token = info.value?.token //读取token
    config.headers.Authorization = token ? "bearer " + token : '' //有token就携带token
    return config
})

5、配置响应拦截器

ins.interceptors.response.use((res) => { //响应拦截器
    if (res.status >= 200 && res.status < 300) { //200-300状态是响应成功,处理响应成功逻辑
        const totalStr = res.headers['x-total-count'] //将请求头携带的数据赋值给totalStr
        if (totalStr) { //判断,有就返回data和total属性的对象
            return {
                data: res.data,
                total: parseInt(totalStr)
            }
        } else {
            return res.data
        }
    }
    throw new Error('未知错误') //throw是vue3中的抛出一个错误(类似promise)
}, (err) => {
    window.$message.error(err.message) //响应失败就展示后端返回的失败信息(消息提示前面挂载到windows了的,所以可以使用)
})

6、封装 一个请求类型集合函数

function entity(key) { //封装的请求集合,将路由传入进来
    return {  //返回一个属性是函数的对象(调用对应请求对象,可传入数据)
        get(params) {
            return ins.get('/' + key, { params })
        },
        post(data) {
            return ins.post('/' + key, data)
        },
        put(id, data) {
            return ins.put('/' + key + '/' + id, data)
        },
        patch(id, data) {  //打补丁,哪里修改就改哪里
            return ins.patch('/' + key + '/' + id, data)
        },
        delete(id) {
            return ins.delete('/' + key + '/' + id)
        },
        deleteAll(ids) {
            const req = (id) => {
                return ins.delete('/' + key + '/' + id)
            }
            return Promise.allSettled(ids.map(req))
        }
    }
}

7、封装导出一个对象,对象属性名就是对应的请求方法,属性值就是调用上方的请求集合函数,并在此处写入请求路径参数

export const apis = { //封装的api请求对象
    users: entity('users'),
    schools: entity('schools'),
    dynamicCategories: entity('dynamicCategories'),
    dynamicContents: entity('dynamicContents'),
    carousels: entity('carousels'),
    studentSources: entity('studentSources'),
    studentSourceStates: entity('studentSourceStates'),
    studentSourceLevel: entity('studentSourceLevel'),
    studentsBefore: entity('studentsBefore'),
}

8、封装一个上传文件的方法

// 上传文件
export function upload(file) { //手动封装的上传文件,参数为file文件
    const formData = new FormData() //文件需要formData格式,这里new一个FormData实例
    formData.append('file', file) //将传来的file丢入formData里
    return fetch(baseURL + '/file', { //用fetch发请求
        method: "POST",
        body: formData
    }).then(res => res.text()).then(res => baseURL + res)
  //上一行中,.text()是让其返回文本格式数据
}


    其他组件或者js代码需要用到请求时,可以直接import 导入对应的方法即可使用

fetch请求的理解:

流程:请求->一帧一帧地发给后端->后端进行处理->一帧一帧地返回给前端。每一帧,都包含头信息和状态码

xhr.onProgress每一帧触发,得到数据量

fetch  res.body是一个可读流,流的读取也可以记录进度

详细描述:

1、原生请求,fetch xhr一样的功能,只是fetch是Promise风格

2、fetch第一个参数是url,第二个参数是配置项

3、fetch可以配置:method请求方法,headers请求头,body请求体

4、fetch请求如果发送get/dalete,参数放在-----路径参数(path/params),查询参数(?key=value&key=value)

5、fetch接收的数据有两段,第一段描述信息,还没有返回结束,只是第一帧的http,能拿到status状态码,htaders返回头,决定使用何种方式处理返回体:res.json解析成对象,res.text解析成文本,res.blob解析成文件

6、fetch第二段then,返回体解析后的结果

fetch请求基本使用:

fetch(url, {
  method, // 请求方法
  headers, // 请求头
  body, // 二进制或字符串
}).then(res=>{
  // 在返回第一帧的时候执行
  // res.headers 返回头
  // res.status 返回状态码
  return res.json() // text/blob
}).then(res=>{
  console.log(res) // 结果
})

fetch请求封装:

1、闭包原理,内层函数访问外层函数变量的引用

2、内层函数可以当做请求拦截器,可以做一些请求之前的处理,例如携带token

3、then可以看做响应拦截器,可以做对数据进行结构处理,以及判断并确定返回数据的类型

// 路径参数和查询参数在 path 传进来
function request(method, path, data){
  // 组装基地址
  let url = baseUrl + path
  // 可以看成 axios 请求拦截器
  return fetch(url, {
    method,
    body: data?JSON.stringify(data):undefined,
    headers:{
      "Authorization":"Bearer " + localStorage.getItem('token')
    }
  }).then(res=>{
    // 可以看成 axios 的响应拦截器
    if(res.status >=200 && res.status < 300){
      return res.json()
    }else{
      throw new Error(res.status)
    }
  }).catch(err=>{
    // 错误处理
  })
}


request('GET', `/users?name=${name}`)

请求封装个人随笔结尾:

本站文章均原创,可以转载,禁止克隆。关于请求封装有更好的理解则可以评论在下方,投稿可以直接联系站长或者发入投稿邮箱!