美文网首页Axios
Vue自用ES6 Async 风格的api请求文件封装(fetc

Vue自用ES6 Async 风格的api请求文件封装(fetc

作者: 布可booker | 来源:发表于2020-01-03 11:23 被阅读0次

api调用实例

...
methed: {
  ...
  // 根据账户查询用户的api
  async getUser() {
    const {account} = this
    const data = {
      account 
    }
    await this.$api
              .getUsers({
                data,
                // 成功回调
                onSuccess: res => {
                  // ?. 为选择链式调用, 如果data为null, 不会报错,会返回undefined, 需要polify
                  let list = res ?.data ?.pageData || []
                  // 处理数据
                  list.forEach((item, index) => {
                    item.children && delete item.children;
                    item.key = index
                  });
                  this.list = list;
                }
              })
  },
  mounted() {
    this.loading = true
    await this.getUser()

    await this.anotherApi
    await this.anotherApi
    await this.anotherApi

    this.loading = false
  }
  ...
}

请求前, 可以打开loading开关, await 调用接口请求函数, 可以在请求完成后, 再继续运行程序, 关闭loading开关

fetch.js封装过程

  • axios

  import axios from 'axios'

axios中文文档

axios 是一个基于 promise 用于浏览器和 nodejs 的 http 客户端,本身具有以下特征:

  • 从浏览器中创建 XMLHttpRequest
  • 从 nodejs 发出 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 自动转换 JSON 数据
  • 客户端支持防止 CSRF / XSRF

axios 对vue有非常高的支持度, 很多vue项目都是用axios作为api请求插件. 网上也有非常多对axios进行二次封装的文章, 笔者也是参考了总多封装方法, 最后自己修改设计了这套自用模板. axios的具体是用方法此处就不详细介绍, 如果对axios还不是非常熟悉, 可以直接访问文档进行学习.

除了axios, 也还有fetch等其他api请求方案, 也可以根据不同的请求方案, 对fetch.js文件进行修改, 以满足需求.

  • message

import {
  notification
} from 'ant-design-vue'
...
function message(msg) {
  notification.error({
    message: "服务器请求异常",
    description: "提示:" + msg
  })
}

message 模块是用于接口提示信息抛出的模块. 比如, 一个修改数据的接口, 在接口请求成功后, 返回成功code. 此时就可以用message弹出一个提示信息, 提示用户修改成功. 请求失败也是同理, 可以抛出失败原因等.可以根据项目, 修改对应的组件. 例如element的 messageBox等.

  • defaultSetting

// 默认请求配置
const defaultSetting = {
  // 请求方法
  method: 'GET',
  // 超时时间ms
  timeout: 600000,
  // res.code成功判定范围
  statusMin: 0,
  statusMax: 99999,
  // 全局失败回调
  onGlobalFail: function (res) {
    message(res.message || res.msg)
  },
  // 成功条件计算方法
  computeSuccess: function (res) {
    if (res.status > 299) return false
    return 1 === res.data.code
  }
}

defaultSetting默认设置, 这里可以配置一些默认参数

  • method 请求方法(GET, PSOT, ...)

  • timeout 请求超时判断时间ms

  • statusMin, statusMax 请求返回状态码判定成功的范围,例如min设置为200, max设置为399. 则403, 404等状态码的请求会被判定为请求失败, 执行请求失败分支.(这个状态码配置的是aixos插件的成功判断, 由于笔者自己写了成功与失败的分支, 所以这里设置了0-99999都为成功, 即所有情况下都把结果返回, 由自定义的方法去判断请求是否成功)

  • onGlobalFail [Function] 全局失败回调. 这个方法可以接受一个res的参数,即请求结果. 当自定义方法判定请求失败时执行.此方法默认为全局方法, 会应用于所有请求. 这个方法默认为使用之前定义的message方法, 弹出一个提示框, 展示失败信息. 可以在调用具体接口时覆盖此方法.

  • computeSuccess 此方法用于计算成功状态,接受res参数, 即请求结果. 此方法返回一个boolean值, true时执行请求成功逻辑, false时执行请求失败逻辑.

  • config


export default async ({
  // 请求地址
  url = "",
  // `data` 是作为请求主体被发送的数据
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  // - Node 专属: Stream
  data = {},
  // "GET" "POST" ...
  method = defaultSetting.method,
  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout = defaultSetting.timeout,
  // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials = false,
  // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength = 10000,
  // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType = "json",
  validateStatus = (status) => {
    return status >= defaultSetting.statusMin && status < defaultSetting.statusMax; // 默认的
  },
  // `onUploadProgress` 允许为上传处理进度事件
  onUploadProgress = () => {},
  // `onDownloadProgress` 允许为下载处理进度事件
  onDownloadProgress = () => {},
  // `cancelToken` 指定用于取消请求的 cancel token
  // (查看后面的 Cancellation 这节了解更多)
  cancelToken,
  // `params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params,
  // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
  // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
  auth,
  baseUrl,
  // `headers` 是即将被发送的自定义请求头
  headers = {},
  // 成功回调
  onSuccess = function (res) {},
  // 失败回调
  onFail = function (res) {},
  // 全局回调(无论成功失败, 都执行)
  onFinally = function (res) {},
  // 全局成功回调
  onGlobalSuccess = function (res) {},
  // 全局失败回调
  onGlobalFail = defaultSetting.onGlobalFail,
  // 成功条件计算方法
  computeSuccess = defaultSetting.computeSuccess
}) => {...}

这里为fetch.js导出的fetch方法的参数config.其中部分参数被使用于axios请求当中.部分参数被使用于请求后成功与失败逻辑执行.

  • 请求

 let _baseUrl = baseUrl || defaultBaseUrl
  // 如果有redirectUrl, 则覆盖url
  url = _baseUrl + url;
  // 此处规定get请求的参数使用时放在data中,如同post请求
  if (method == "GET") {
    let dataStr = "";
    // 将data参数用?&拼接
    dataStr = Object.entries(data).reduce((dataStr, value) => {
      dataStr = dataStr + `${value[0]}=${value[1]}&`
      return dataStr
    }, dataStr)
    if (dataStr !== "") {
      dataStr = dataStr.substr(0, dataStr.lastIndexOf("&"));
      url = url + "?" + dataStr;
    }
  }

此处拼接url

// config
let requestConfig = {
  url,
  method: method, // 默认是 get
  headers,
  params,
  data,
  timeout,
  withCredentials,
  auth,
  responseType, // 默认的
  onUploadProgress,
  onDownloadProgress,
  maxContentLength,
  cancelToken,
  validateStatus
}

用于aixos请求的config

// 发送请求
await axios(requestConfig).then(res => {
  // 允许实例自行计算成功条件
  const isSuccess = computeSuccess(res)
  const result = res.data
  // 成功码默认为1, 根据后台修改
  if (isSuccess) {
    onGlobalSuccess(result)
    onSuccess(result)
  } else {
    onGlobalFail(result)
    onFail(result)
  }
  onFinally(res)
})

发送请求, 通过computeSuccess计算出成功状态码, 运行对应分支逻辑

  • 完整的fetch.js

import axios from 'axios'

import {
  notification
} from 'ant-design-vue'

const defaultBaseUrl = "http://192.168.0.1"; // 线上
// 默认请求配置
const defaultSetting = {
  // 请求方法
  method: 'GET',
  // 超时时间ms
  timeout: 600000,
  // res.code成功判定范围
  statusMin: 200,
  statusMax: 99999,
  // 全局失败回调
  onGlobalFail: function (res) {
    message(res.message || res.msg)
  },
  // 成功条件计算方法
  computeSuccess: function (res) {
    if (res.status > 299) return false
    return 1 === res.data.code
  }
}
// 服务器报错提示款, 可以根据框架修改此函数, msg为抛出信息
function message(msg) {
  notification.error({
    message: "服务器请求异常",
    description: "提示:" + msg
  })
}
export default async ({
  // 请求地址
  url = "",
  // `data` 是作为请求主体被发送的数据
  // 在没有设置 `transformRequest` 时,必须是以下类型之一:
  // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
  // - 浏览器专属:FormData, File, Blob
  // - Node 专属: Stream
  data = {},
  // "GET" "POST" ...
  method = defaultSetting.method,
  // `timeout` 指定请求超时的毫秒数(0 表示无超时时间)
  // 如果请求话费了超过 `timeout` 的时间,请求将被中断
  timeout = defaultSetting.timeout,
  // `withCredentials` 表示跨域请求时是否需要使用凭证
  withCredentials = false,
  // `maxContentLength` 定义允许的响应内容的最大尺寸
  maxContentLength = 10000,
  // `responseType` 表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType = "json",
  validateStatus = (status) => {
    return status >= defaultSetting.statusMin && status < defaultSetting.statusMax; // 默认的
  },
  // `onUploadProgress` 允许为上传处理进度事件
  onUploadProgress = () => {},
  // `onDownloadProgress` 允许为下载处理进度事件
  onDownloadProgress = () => {},
  // `cancelToken` 指定用于取消请求的 cancel token
  // (查看后面的 Cancellation 这节了解更多)
  cancelToken,
  // `params` 是即将与请求一起发送的 URL 参数
  // 必须是一个无格式对象(plain object)或 URLSearchParams 对象
  params,
  // `auth` 表示应该使用 HTTP 基础验证,并提供凭据
  // 这将设置一个 `Authorization` 头,覆写掉现有的任意使用 `headers` 设置的自定义 `Authorization`头
  auth,
  baseUrl,
  // `headers` 是即将被发送的自定义请求头
  headers = {},
  // 成功回调
  onSuccess = function (res) {},
  // 失败回调
  onFail = function (res) {},
  // 全局回调(无论成功失败, 都执行)
  onFinally = function (res) {},
  // 全局成功回调
  onGlobalSuccess = function (res) {},
  // 全局失败回调
  onGlobalFail = defaultSetting.onGlobalFail,
  // 成功条件计算方法
  computeSuccess = defaultSetting.computeSuccess
}) => {
  let _baseUrl = baseUrl || defaultBaseUrl
  // 如果有redirectUrl, 则覆盖url
  url = _baseUrl + url;
  // 此处规定get请求的参数使用时放在data中,如同post请求
  if (method == "GET") {
    let dataStr = "";
    // 将data参数用?&拼接
    dataStr = Object.entries(data).reduce((dataStr, value) => {
      dataStr = dataStr + `${value[0]}=${value[1]}&`
      return dataStr
    }, dataStr)
    if (dataStr !== "") {
      dataStr = dataStr.substr(0, dataStr.lastIndexOf("&"));
      url = url + "?" + dataStr;
    }
  }
  // config
  let requestConfig = {
    url,
    method: method, // 默认是 get
    headers,
    params,
    data,
    timeout,
    withCredentials,
    auth,
    responseType, // 默认的
    onUploadProgress,
    onDownloadProgress,
    maxContentLength,
    cancelToken,
    validateStatus
  }
  // 发送请求
  await axios(requestConfig).then(res => {
    // 允许实例自行计算成功条件
    const isSuccess = computeSuccess(res)
    const result = res.data
    // 成功码默认为1, 根据后台修改
    if (isSuccess) {
      onGlobalSuccess(result)
      onSuccess(result)
    } else {
      onGlobalFail(result)
      onFail(result)
    }
    onFinally(res)
  })
};

api.js

import fetch from "./fetch.js";

export const api = {
  // 1. /login
  loginV2: config =>
    fetch({
      ...config,
      url: "/app/user/loginV2",
      onGlobalFail: function (res) {
        Modal.error({
          title: '登录失败',
          content: res.message || res.msg
        })
      },
      method: "POST"
    }),
  // 2. 获取用户  
  getUser: config =>
    fetch({
      ...config,
      url: "/app/user/findUser",
      method: "POST"
    }),
  ...
};

引入fetch.js, 所有接口添加到api对象中导出. 这里还可以对单个接口进行单独的拦截. 比如所有getUser方法对应的接口不需要弹窗提示, 那么可以在这里修改getUser

  ...
  getUser: config =>
    fetch({
      ...config,
      onGlobalFail: () => {},
      url: "/app/user/findUser",
      method: "POST"
    }),
  ...

这样, 如果这个接口在多个页面都进行了调用, 则无需挨个修改了.

main.js

...
import {
  api
} from './api/api'

Vue.prototype.$api = api;
...

将api挂载到Vue原型

以上, 完成这行动作后, 我们就能通过this.$api这种方式调用接口了.

mock

开发时,我们经常需要一些虚拟数据.那么, 我们可以写一个mock.js用于mock数据.

mock.js

export const loginData = {
  "code": 1,
  "msg": "success",
  "data": {
    "userId": 1,
    "account": "2222222222",
    "role": 3,
    "password": null,
    "phone": "21121211221",
    "email": null,
    "unionId": null,
    "reName": null,
    "nickName": "xxx2",
    "accId": "dee2d504239649b6be54c1279926a4a7",
    "ytxAccount": "852b83a42d424f36bb9ef7d383acc08d",
    "headPic": "http://k1VoaL3.wlekjwqejklwq",
    "gender": 0,
    "age": null,
    "birthday": null,
    "constellation": null,
    "bloodType": null,
    "profession": null,
    "address": null,
    "contact": null,
    "studyCfNum": null,
    "teacherCfNum": null,
    "state": 0,
    "createTime": "2016-12-27 13:20:43",
    "lastUpdateTime": "2019-12-12 09:01:59",
    "lastLoginTime": "2020-01-02 17:50:14",
    "balance": null,
    "orgno": "00000768",
    "schoolName": null,
    "isBind": null,
    "onlineState": null,
    "userDevices": [],
    "classList": [],
    "clazzList": [],
    "children": [],
    "usrChildren": [],
    "fileStore": null,
    "popenId": "oFwyg4vN-Wv9LMwNKafeeeeeWexM",
    "topenId": "ohH6X5JSLwHzwYNewqewqecagVeaw"
  }
}

mockedApi

import fetch from "./fetch.js";
import {
  loginData
} from './mock.js'
export const api = {
  // 1. /login
  loginV2: config => config.onSuccess(loginData),
};

修改main.js中的api导入路径为 mockedApi.js. 这样, 当后台接口开发完毕, 只要把路径再改回去正式的接口这一个步骤, 就完成了mock数据到正式接口数据的变更, 十分便利.

相关文章

  • Vue自用ES6 Async 风格的api请求文件封装(fetc

    api调用实例 请求前, 可以打开loading开关, await 调用接口请求函数, 可以在请求完成后, 再继续...

  • 上传

    axios封装 上传api.js api.js vue文件

  • VUE 请求api的封装

    1.常用封装一(跟element-admin相同) * 1.1在脚手架目录utils目录新建一个request.j...

  • vue封装axios

    最近在学习ES6,正好项目用到vue,axios封装请求,写的不好,欢迎大神指教。 环境安装 vue官网vue-c...

  • vue项目后台接口管理

    前言 上篇文章axios二次封装及API接口统一管理讲到了vue项目中的axios请求api统一的封装,但是api...

  • mpvue中配置axios使用

    mpvue中使用axios 1.api的index.js文件下配置axios 2.api下新建page文件封装请求...

  • axios封装

    index.js------axios封装 api.js------接口文件 单页面引入---login.vue ...

  • VUE获取请求进度

    onUploadProgress 允许为上传处理进度的事件,是axios的请求配置之一。 封装axios的fetc...

  • nui-app里面的请求接口简单的封装

    nui-app里面的请求接口简单的封装 新建一个封装接口的文件 挂在到Vue原型上 要请求接口的页面

  • 掌握技能

    (持续更新 ——) 闭包 原型 Dom API Bom API 作用域 es6变量声明 promise async...

网友评论

    本文标题:Vue自用ES6 Async 风格的api请求文件封装(fetc

    本文链接:https://www.haomeiwen.com/subject/owlzoctx.html