HTTP请求封装 & 拦截器的使用

  • Post author:
  • Post category:其他


文中代码部分来源于:https://blog.csdn.net/weixin_56947857/article/details/115908520



新建request.js,主要用于建立请求和响应拦截

import axios from 'axios'
import { Message, MessageBox } from 'element-ui'//请根据自己的情况自信修改
import store from '../store'  

// 创建axios实例
const service = axios.create({
  baseURL: process.env.BASE_API, // api 的 base_url
  timeout: 50000 // 请求超时时间
})

// request拦截器
service.interceptors.request.use(
  config => {
    // config.headers['Content-Type'] = 'application/json'
    if (store.getters.token) {
      config.headers['Authorization'] = 'Bearer ' + store.getters.token
       // 让每个请求携带自定义token 请根据实际情况自行修改
    }
    return config
  },
  error => {
    // Do something with request error
    console.log(error) // for debug
    Promise.reject(error)
  }
)

// response 拦截器
service.interceptors.response.use(
  response => {
    /**
     * code为201-206的暂时定为正确 可结合自己业务进行修改
     */
    const res = response
    if (res.status < 200 || res.status > 299) {
      Message({
        message: res.statusText,
        type: 'error',
        duration: 5 * 1000
      })

      if (res.status === 401 || res.status === 403) {
        MessageBox.confirm(
          '你已被登出,可以取消继续留在该页面,或者重新登录',
          '确定登出',
          {
            confirmButtonText: '重新登录',
            cancelButtonText: '取消',
            type: 'warning'
          }
        ).then(() => {
          store.dispatch('oidc/signOutOidc');
        })
      }
      return Promise.reject('error')
    } else {
      return response.data
    }
  },
  error => {
    if (error.response) {
      Message({
        message: error.response.data.error.details,
        type: 'error',
        duration: 5 * 1000
      })
      console.log('err' + error.response.data) // for debug
    } else {
      Message({
        message: error.message,
        type: 'error',
        duration: 5 * 1000
      })
      console.log('err' + error.message) // for debug
    }
    return Promise.reject(error)
  }
)

export default service



新建api.js,用于封装各种类型的HTTP请求

顺便说说常见HTTP请求方式及其区别。


HTTP请求的方法:

  • HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式
  • HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。
  • HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法


HTTP1.0 HTTP1.1 HTTP2.0 主要特性对比

请求类型 描述 其他特点
GET 向特定的资源发出请求 查看所有任务或根据ID查看一个任务

1)

URL长度有限制

,各个浏览器要求都不一样,IE最短(2083字符,中文字符的话只有2083/9=231)

2)

会被浏览器主动缓存


3)参数直接暴露在URL上,所以不能用来传递敏感信息

4)请求参数会被完整保留在浏览器历史记录里
POST 向指定资源提交数据进行处理请求 新建一个任务,例如提交表单或者上传文件。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改

1)

URL长度没有限制


2)

不会被浏览器缓存


3)请求参数不会被保存
PUT 向指定资源位置上传其最新内容 更新任务,其他特征和POST类似
DELETE 请求服务器删除 Request-URI 所标识的资源 删除任务
OPTIONS 查询Web服务器的性能 由浏览器自动发起,目的就是去服务器检查一下接下来要到用的方法(GET、POST、PUT、detele)在服务器上是否支持。发起条件:

1) 跨域调用;

2)自定义头部;

3)请求头application/x-www-form-urlencoded、multipart/form-data、text/plain之外的格式
HEAD 跟GET一样,只是仅返回头部信息,不返回消息体 常用来测试链接的有效性,可达性,以及最近的修改信息
TRACE 回显服务器收到的请求 主要用于测试或诊断
CONNECT HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器

虽然 HTTP 的请求方式有 8 种,但是我们在实际应用中常用的也就是 get 和 post,其他请求方式也都可以通过这两种方式间接的来实现。


api.js示例代码

import request from "@/utils/request"; //引入上面封装好的request.js
import qs from 'qs'   //qs是一个增加了一些安全性的查询字符串解析和序列化字符串的库。npm install qs

// get请求方式
export function getConsumeByPhone(query) {
  return request({
    url: `/v1_consume/getConsumeByPhone`,
    method: "get",
    params: query
  });
}
	
// post请求方式
export function addLeaveMessage(query) {
  return request({
    url: `/v2_leave/addLeaveMessage`,
    method: "post",
    data: qs.stringify(query),
  });
}

//delete请求方式
export function deleteByIdCard(id) {
    return request({
      url: `/card/deleteById/${id.id}/${id.updater}`,
      method: "delete"
   });
}
   
//下面说说data数据上传

//当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串
(name1=value1&name2=value2…),然后把这个字串append到url后面,用?分割,加载这个
新的url。

export function getOpenId(query) {
  return request({
    url: `/v1_auth/getOpenId`,
    method: "post",
    data: qs.stringify(query),
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded'
    }
  });
}

// data上传2
export function getCode(query) {
  return request({
    headers: {
      'Content-Type': 'application/json'
     },
    url: `/v1_global/getCode`,
    method: "post",
    data: qs.stringify(query),
  });
}
// **当action为post时候,浏览器把form数据封装到http body中,然后发送到server。
 如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。 
 但是如果有type=file的话,就要用到multipart/form-data了。浏览器会把整个表单以控件
 为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type
 (默认为text/plain),name(控件name)等信息,并加上分割符(boundary)。**

export function upload(query) {
  return request({
    headers: {
      'Content-Type': 'multipart/form-data'
     },
    url: `v1_global/upload`,
    method: "post",
    data: query
  });
}

//  data上传4
export function uploadFace(query) {
  return request({
    headers: {
      'Content-Type': 'applic/v1_pFace/uploadFace'
    },
    url: `/v1_pFace/uploadFace`,
    method: "post",
    data: query
  });
}

使用时直接引入即可,vue写法参照

import { uploadFace } from '@/api/api'



qs的作用

POST提交数据有两种数据传输方式,FormData和payload,这两种方式浏览器是通过Content-Type来进行区分:


Payload    Content-Type: 'application/json; charset=utf-8'



Form Data   Content-Type: 'application/x-www-form-urlencoded'

axios默认的content-type是application/json,传输的样式是

{
    name:'小明',
    age:'29'
}

如果使用的qs进行序列化,(注:qs.stringify()将对象序列化成URL的形式,以&进行拼接。安装axios即可使用qs。)那么content-type就是application/x-www-form-urlencoded,也就是常说的表单提交,传输的样式是FormData

name:'小明', 
age:'29'

后台urlencoding后是

name='小明'&age='29'

对比下JSON.stringify。JSON是正常类型的JSON,

var a = {name:'hehe',age:10};
 qs.stringify(a)
// 'name=hehe&age=10'
JSON.stringify(a)
// '{"name":"hehe","age":10}'

是否需要用qs去序列化参数完全取决于后端要怎么接受数据。

实例:

var qs = require("qs");
export const AxiosPost = (url, params) => { 
    return axios.post(url,qs.stringify(params), {
    	headers: {"Content-Type": "application/x-www-form-urlencoded" } 
    })
}


post需要用qs.stringify而get请求时不用

原因:HTTP请求中的get请求和post请求参数的存放位置是不一样的,get请求的参数以键值对的方式跟在url后面的,而post请求的参数是以键值对的方式在请求体里的,用Qs.stringify()就是把传入的对象转换为键值对。



版权声明:本文为huhm_evget原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。