axios参考:https://github.com/axios/axioshttp://www.axios-js.com/zh-cn/docs/#axios-delete-url-config-1https://axios.nuxtjs.org/usage

axios封装参考:https://blog.csdn.net/weixin_44356673/article/details/107467614

nuxt使用参考:https://blog.csdn.net/qq_41387882/article/details/106294485

axios的封装

在plugins中创建axios_interceptors.js文件,封装axios

  1. const qs = require('qs');
  2. import Vue from 'vue'
  3. export default function ({ $axios, store }, inject) {
  4. const myAxios = $axios.create({
  5. timeout: 1000 * 60
  6. })
  7. // ! 响应的拦截
  8. /**
  9. * todo 提示函数
  10. * 禁止点击蒙层、显示一秒后关闭
  11. */
  12. const tip = msg => {
  13. Vue.prototype.$message.error(msg, 10);
  14. }
  15. /**
  16. * todo 跳转登录页
  17. * 携带当前页面路由,以期在登录页面完成登录后返回当前页面
  18. */
  19. const toLogin = () => {
  20. // router.replace({
  21. // path: '/login',
  22. // query: {
  23. // redirect: router.currentRoute.fullPath
  24. // }
  25. // })
  26. window.onNuxtReady(() => {
  27. window.$nuxt.$router.replace({
  28. path: '/login',
  29. query: {
  30. // 保存上一个页面的访问路径
  31. redirect: router.currentRoute.fullPath
  32. }
  33. })
  34. })
  35. }
  36. /**
  37. * todo 请求失败后的错误统一处理
  38. * @param {Number} status 请求失败的状态码
  39. */
  40. const errorHandle = (status, msg) => {
  41. switch (status) {
  42. // 401: 未登录
  43. // 1. 跳转登录页面,并携带当前页面的路径
  44. // 2. 在登录成功后返回当前页面,这一步需要在登录页操作。
  45. case 401:
  46. toLogin()
  47. break
  48. // 403 token过期
  49. // 登录过期对用户进行提示
  50. // 清除本地token和清空vuex中token对象
  51. // 跳转登录页面
  52. case 403:
  53. tip('登录过期,请重新登录')
  54. // 清除token
  55. localStorage.removeItem('token')
  56. store.commit('loginSuccess', null)
  57. // 跳转登录页面,并将要浏览的页面fullPath传过去,登录成功后跳转需要访问的页面
  58. setTimeout(() => {
  59. toLogin()
  60. }, 1000)
  61. break
  62. // 404请求不存在
  63. case 404:
  64. tip('网络请求不存在')
  65. break
  66. case 504:
  67. tip('服务器错误')
  68. break
  69. // 其他错误,直接抛出错误提示
  70. default:
  71. tip(msg)
  72. break
  73. }
  74. }
  75. // todo 移除 loding
  76. const removeLoding = (url) => {
  77. console.log(url, 'removeLoading');
  78. store.commit('loading/removeLoadingCount');
  79. }
  80. // todo 请求拦截
  81. myAxios.onRequest(config => {
  82. // todo 解决get请求传递数组参数出现 [ ] 解决方法
  83. if (config.method === 'get') {
  84. // 格式化get的请求参数
  85. config.paramsSerializer = function (params) {
  86. // qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'indices' }) // 'a[0]=b&a[1]=c'
  87. // qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'brackets' }) // 'a[]=b&a[]=c'
  88. // qs.stringify({ a: ['b', 'c'] }, { arrayFormat: 'repeat' }) // 'a=b&a=c'
  89. return qs.stringify(params, { arrayFormat: 'repeat' })
  90. }
  91. }
  92. // 登录流程控制中,根据本地是否存在token判断用户的登录情况
  93. // 但是即使token存在,也有可能token是过期的,所以在每次的请求头中携带token
  94. // 后台根据携带的token判断用户的登录情况,并返回给我们对应的状态码
  95. // 而后我们可以在响应拦截器中,根据状态码进行一些统一的操作。
  96. const token = store.state.token
  97. token && (config.headers.Authorization = token)
  98. return config
  99. })
  100. // todo 请求失败
  101. myAxios.onRequestError(error => Promise.error(error))
  102. // todo 返回成功
  103. // 如果返回的状态码为200 并且为ACK,说明接口请求成功,可以正常拿到数据
  104. // 否则的话抛出错误
  105. myAxios.onResponse(res => {
  106. removeLoding(res.config.url) // 移除loading
  107. // console.log(res, '=====');
  108. return res.status === 200 ? Promise.resolve(res) : Promise.reject(res)
  109. })
  110. // todo 返回失败
  111. // 这里可以跟你们的后台开发人员协商好统一的错误状态码
  112. // 然后根据返回的状态码进行一些操作,例如登录过期提示,错误提示等等
  113. // 下面列举几个常见的操作,其他需求可自行扩展
  114. myAxios.onResponseError(error => {
  115. removeLoding() // 移除loading
  116. console.log(error, '======')
  117. const { response } = error
  118. console.log(response)
  119. if (response) {
  120. // 请求已发出,但是不在2xx的范围
  121. errorHandle(response.status, response.data.message)
  122. return Promise.reject(response)
  123. } else {
  124. console.log('========================== aaa');
  125. // 处理断网的情况
  126. // eg:请求超时或断网时,更新state的network状态
  127. // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
  128. // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
  129. store.commit('changeNetwork', false)
  130. }
  131. })
  132. // 重写axios的方法----统一处理请求参数
  133. myAxios.$get = (...arg) => {
  134. return fn('get', ...arg)
  135. }
  136. myAxios.$post = (...arg) => {
  137. return fn('post', ...arg)
  138. }
  139. myAxios.$put = (...arg) => {
  140. return fn('put', ...arg)
  141. }
  142. /**
  143. * ! 公共请求方法
  144. * @param {String} url [请求的url地址]
  145. * @param {Object} params [请求时携带的参数]
  146. * @param {Object} options [其他配置]
  147. * 如果返回500,是因为后台判断不是ajax请求,需要传递 headers
  148. headers: {
  149. 'x-requested-with': 'XMLHttpRequest',
  150. "x-form-id": "mob-form"
  151. }
  152. */
  153. function fn (methods, ...arg) {
  154. let [url, params, options = {}] = arg
  155. let opts = Object.assign({
  156. loading: true,
  157. tip: true
  158. }, options)
  159. // 添加loading
  160. if (opts.loading) {
  161. console.log(url, 'loding', methods);
  162. store.commit('loading/addLoadingCount')
  163. }
  164. const baseUrl = process.env.baseURL
  165. return new Promise((resolve, reject) => {
  166. // axios的请求要求是get或delete的时候参数是放在对象中的params下面的
  167. params = methods === 'get' || methods === 'delete' ? { params } : params
  168. let requestData = {}
  169. if (opts.headers) {
  170. requestData.headers = opts.headers
  171. }
  172. myAxios[methods](baseUrl + url, params, requestData).then(res => {
  173. if (res && res.data && res.data.code === 'ACK') {
  174. resolve(res.data)
  175. } else {
  176. (res && opts.tip) && tip(res.data.message)
  177. reject(res)
  178. }
  179. })
  180. })
  181. }
  182. // myAxios.myGet = function () {}
  183. // Inject to context as $api
  184. inject('myAxios', myAxios)
  185. }

使用封装的axios

在plugins中创建api/api.js

  1. // 接收inject的myAxios
  2. export default function({$myAxios, store}, inject) {
  3. inject('api', {
  4. // 因为$myAxios无法获取,所以只能传入
  5. user: require('./user.js').mount($myAxios),
  6. })
  7. }

user.js

  1. export function mount (axios) {
  2. return {
  3. // 获取用户信息
  4. getUser: async (id, ...arg) => {
  5. return await axios.$post('/sys-user/' + id, ...arg)
  6. },
  7. }
  8. }

使用用户信息接口

  1. // todo 第一种
  2. this.$api.user.getUser('11', {param: 11}, {loading: false}).then(result => {
  3. // 成功的回调
  4. }, err => {
  5. 失败的回调
  6. })
  7. // todo 第二种
  8. les result = await this.$api.user.getUser('11', {param: 11}, {loading: false}).catch((err) => {
  9. // 捕捉异常的情况
  10. console.log(err)
  11. })

插件在nuxt.js中的配置

  1. plugins: [
  2. '@/plugins/antd-ui', // UI框架
  3. "@/plugins/axios_interceptors", // 在client和service上生效
  4. "@/plugins/api/api", // 在client和service上生效
  5. ],
  6. // 使用axios的模块
  7. // Modules: https://go.nuxtjs.dev/config-modules
  8. modules: [
  9. '@nuxtjs/axios',
  10. '@nuxtjs/style-resources'
  11. ],