人民医院前端

request.js 7.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. import axios from "axios";
  2. import qs from "qs"; // 引入axios时同时引入qs即可。
  3. import { Message, MessageBox } from "element-ui";
  4. import store from "../store";
  5. import { getToken } from "@/utils/auth";
  6. // 正在进行中的请求列表
  7. const reqList = [];
  8. /**
  9. * 阻止重复请求
  10. * @param {array} reqList - 请求缓存列表
  11. * @param {string} url - 当前请求地址
  12. * @param {function} cancel - 请求中断函数
  13. * @param {string} errorMessage - 请求中断时需要显示的错误信息
  14. */
  15. const stopRepeatRequest = function(reqList, url, cancel, errorMessage) {
  16. const errorMsg = errorMessage || "";
  17. for (let i = 0; i < reqList.length; i++) {
  18. if (reqList[i] === url) {
  19. cancel(errorMsg);
  20. return;
  21. }
  22. }
  23. reqList.push(url);
  24. };
  25. /**
  26. * 允许某个请求可以继续进行
  27. * @param {array} reqList 全部请求列表
  28. * @param {string} url 请求地址
  29. */
  30. const allowRequest = function(reqList, url) {
  31. for (let i = 0; i < reqList.length; i++) {
  32. if (reqList[i] === url) {
  33. reqList.splice(i, 1);
  34. break;
  35. }
  36. }
  37. console.log(reqList);
  38. };
  39. axios.interceptors.request.use(
  40. config => {
  41. if (config.method === "post") {
  42. config.data = qs.stringify(config.data);
  43. }
  44. return config;
  45. },
  46. error => {
  47. return Promise.reject(error);
  48. }
  49. );
  50. // const baseURL = process.env.BASE_API
  51. // 创建axios实例
  52. const service = axios.create({
  53. // baseURL: baseURL, // api的base_url axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
  54. timeout: 30000, // 请求超时时间
  55. headers: {
  56. "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
  57. },
  58. // `transformRequest` 允许在向服务器发送前,修改请求数据
  59. // 只能用在 'PUT', 'POST' 和 'PATCH' 这几个请求方法
  60. // 后面数组中的函数必须返回一个字符串,或 ArrayBuffer,或 Stream
  61. // 解决axios默认发送数据时,数据格式是Request Payload的问题
  62. transformRequest: [
  63. function(data) {
  64. // 对 data 进行任意转换处理
  65. return qs.stringify(data);
  66. }
  67. ],
  68. // `paramsSerializer` 是一个负责 `params` 序列化的函数
  69. // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
  70. // return qs.stringify({ids: [1, 2, 3]}, {indices: false}) // 形式:ids=1&ids=2&id=3
  71. // return qs.stringify({ids: [1, 2, 3]}, {arrayFormat: 'indices'}) // 形式:ids[0]=1&ids[1]=2&ids[2]=3
  72. // return qs.stringify({ids: [1, 2, 3]}, {arrayFormat: 'brackets'}) // 形式:ids[]=1&ids[]=2&ids[]=3
  73. // return qs.stringify({ids: [1, 2, 3]}, {arrayFormat: 'repeat'}) // 形式: ids=1&ids=2&id=3
  74. paramsSerializer: function(params) {
  75. return qs.stringify(params, { arrayFormat: "indices" }); // 形式:ids=1&ids=2&id=3
  76. }
  77. });
  78. // request拦截器
  79. service.interceptors.request.use(
  80. config => {
  81. if (store.getters.token) {
  82. // config.headers["Authorization"] = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改 Bearer
  83. }
  84. config.url = config.url + "?token=" + getToken();
  85. let cancel;
  86. if (config.method === "post") {
  87. // 设置cancelToken对象
  88. config.cancelToken = new axios.CancelToken(function(c) {
  89. cancel = c;
  90. });
  91. // 阻止重复请求。当上个请求未完成时,相同的请求不会进行
  92. stopRepeatRequest(
  93. reqList,
  94. config.url,
  95. cancel,
  96. `${config.url} 请求被中断`
  97. );
  98. // stopRepeatRequest(reqList, config.url, cancel, `请求被中断`)
  99. } else {
  100. }
  101. return config;
  102. },
  103. error => {
  104. // Do something with request error
  105. Promise.reject(error);
  106. }
  107. );
  108. // respone拦截器
  109. service.interceptors.response.use(
  110. response => {
  111. /**
  112. * state为非"success"时抛错
  113. */
  114. // 增加延迟,相同请求不得在短时间内重复发送
  115. if (response.config.method === "post") {
  116. setTimeout(() => {
  117. const replaceList = response.config.url.split("/");
  118. const newUrl =
  119. replaceList[replaceList.length - 2] +
  120. "/" +
  121. replaceList[replaceList.length - 1];
  122. allowRequest(reqList, newUrl);
  123. }, 1000);
  124. }
  125. const res = response.data;
  126. if (res.state && res.state.toLowerCase() !== "success") {
  127. Message({
  128. message: res.message,
  129. type: "error",
  130. duration: 5 * 1000
  131. });
  132. // 50008:非法的token; 50012:其他客户端登录了; "notoken":Token 过期了
  133. if (
  134. res.state.toLowerCase() === 50008 ||
  135. res.state.toLowerCase() === 50012 ||
  136. res.state.toLowerCase() === "notoken"
  137. ) {
  138. MessageBox.confirm(
  139. "你已被登出,可以取消继续留在该页面,或者重新登录",
  140. "确定登出",
  141. {
  142. confirmButtonText: "重新登录",
  143. cancelButtonText: "取消",
  144. type: "warning"
  145. }
  146. ).then(() => {
  147. store.dispatch("FedLogOut").then(() => {
  148. location.reload(); // 为了重新实例化vue-router对象 避免bug
  149. });
  150. });
  151. }
  152. return Promise.reject("error");
  153. } else {
  154. if (response.config.responseType === "blob") {
  155. return response;
  156. }
  157. return response.data;
  158. }
  159. },
  160. error => {
  161. if (error && !error.message && error.response.config.method === "post") {
  162. setTimeout(() => {
  163. const replaceList = error.response.config.url.split("/");
  164. const newUrl =
  165. replaceList[replaceList.length - 2] +
  166. "/" +
  167. replaceList[replaceList.length - 1];
  168. allowRequest(reqList, newUrl);
  169. }, 500);
  170. }
  171. console.log("err:" + error); // for debug
  172. if (error && error.response) {
  173. switch (
  174. error.response.status // 跨域存在获取不到状态码的情况
  175. ) {
  176. case 400:
  177. error.message = `请求错误(400):${error.response.config.url}`;
  178. break;
  179. case 401:
  180. error.message = `未授权,请登录(401):${error.response.config.url}`;
  181. store.dispatch("FedLogOut").then(() => {
  182. location.reload(); // 为了重新实例化vue-router对象 避免bug
  183. });
  184. break;
  185. case 403:
  186. error.message = `拒绝访问(403):${error.response.config.url}`;
  187. break;
  188. case 404:
  189. error.message = `请求地址出错(404): ${error.response.config.url}`;
  190. break;
  191. case 408:
  192. error.message = `请求超时(408):${error.response.config.url}`;
  193. break;
  194. case 500:
  195. error.message = `服务器内部错误(500):${error.response.config.url}`;
  196. break;
  197. case 501:
  198. error.message = `服务未实现(501):${error.response.config.url}`;
  199. break;
  200. case 502:
  201. error.message = `网关错误(502):${error.response.config.url}`;
  202. break;
  203. case 503:
  204. error.message = `服务不可用(503):${error.response.config.url}`;
  205. break;
  206. case 504:
  207. error.message = `网关超时(504):${error.response.config.url}`;
  208. break;
  209. case 505:
  210. error.message = `HTTP版本不受支持(505):${error.response.config.url}`;
  211. break;
  212. default:
  213. error.message = `连接错误:${error.response.status}`;
  214. break;
  215. }
  216. } else if (error.message.indexOf("请求被中断") !== -1) {
  217. error.message = "请勿重复请求!";
  218. } else {
  219. error.message = "网络出现问题,请稍后重试!";
  220. }
  221. Message({
  222. message: error.message,
  223. type: "error",
  224. duration: 5 * 1000
  225. });
  226. return Promise.reject(error);
  227. }
  228. );
  229. export default service;