useFetch.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import { message } from 'antd';
  2. import { getApiUrl } from '@/utils/common';
  3. import {
  4. getLoginUrl,
  5. getUserSession,
  6. redirectToHome,
  7. redirectToLogin,
  8. } from '@/utils/user';
  9. export type RequestModel = {
  10. params?: object;
  11. headers?: object;
  12. signal?: AbortSignal;
  13. };
  14. export type RequestWithBodyModel = RequestModel & {
  15. body?: object | FormData;
  16. };
  17. const readResponse = async (response: Response) => {
  18. if (!response.headers) {
  19. return response;
  20. }
  21. const contentType = response.headers.get('content-type');
  22. const contentDisposition = response.headers.get('content-disposition');
  23. if (contentType === null) {
  24. return null;
  25. } else if (contentType.indexOf('application/json') !== -1) {
  26. return await response.json();
  27. } else if (contentType.indexOf('text/plain') !== -1) {
  28. return await response.text();
  29. } else if (
  30. contentDisposition != null &&
  31. contentDisposition.indexOf('attachment') !== -1
  32. ) {
  33. return await response.blob();
  34. } else {
  35. return response;
  36. }
  37. };
  38. const handleErrorResponse = async (err: Response) => {
  39. const error = await readResponse(err);
  40. let msg = error?.message || error?.errMessage || error;
  41. switch (err.status) {
  42. case 500:
  43. msg = '内部服务器错误,请稍后再试';
  44. break;
  45. case 401:
  46. redirectToLogin();
  47. return;
  48. case 403:
  49. msg = '资源拒绝授权访问';
  50. redirectToHome(1000);
  51. break;
  52. case 404:
  53. return;
  54. default:
  55. msg =
  56. typeof msg === 'string' && msg !== ''
  57. ? msg
  58. : '操作失败,请稍后再试,或联系技术人员';
  59. }
  60. message.error(msg)
  61. throw error;
  62. };
  63. export const useFetch = () => {
  64. const handleFetch = async (
  65. url: string,
  66. request: any,
  67. signal?: AbortSignal,
  68. ) => {
  69. const apiPrefix = getApiUrl();
  70. const requestUrl = `${apiPrefix}${url}${request?.params ? request.params : ''
  71. }`;
  72. const body = request?.body
  73. ? request.body instanceof FormData
  74. ? { ...request, body: request.body }
  75. : { ...request, body: JSON.stringify(request.body) }
  76. : request;
  77. const headers = {
  78. ...request?.headers,
  79. ...(!request?.body || !(request.body instanceof FormData)
  80. ? { 'Content-type': 'application/json' }
  81. : {}),
  82. Authorization: `Bearer ${getUserSession()}`,
  83. };
  84. return fetch(requestUrl, {
  85. ...body,
  86. headers,
  87. signal,
  88. })
  89. .then(async (response) => {
  90. if (!response.ok) {
  91. throw response;
  92. }
  93. const result = readResponse(response);
  94. return result;
  95. })
  96. .catch(async (err: Response) => {
  97. await handleErrorResponse(err);
  98. });
  99. };
  100. return {
  101. get: async <T>(url: string, request?: RequestModel): Promise<T> => {
  102. return handleFetch(url, { ...request, method: 'get' });
  103. },
  104. post: async <T>(
  105. url: string,
  106. request?: RequestWithBodyModel,
  107. ): Promise<T> => {
  108. return handleFetch(url, { ...request, method: 'post' });
  109. },
  110. put: async <T>(url: string, request?: RequestWithBodyModel): Promise<T> => {
  111. return handleFetch(url, { ...request, method: 'put' });
  112. },
  113. patch: async <T>(
  114. url: string,
  115. request?: RequestWithBodyModel,
  116. ): Promise<T> => {
  117. return handleFetch(url, { ...request, method: 'patch' });
  118. },
  119. delete: async <T>(url: string, request?: RequestModel): Promise<T> => {
  120. return handleFetch(url, { ...request, method: 'delete' });
  121. },
  122. };
  123. };