request.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import Request from "@/lib/request/index.js";
  2. import { refreshTokenFn } from "@/api/login.js";
  3. import storage from "@/utils/storage.js";
  4. import { md5 } from "@/utils/md5.js";
  5. import Foundation from "@/utils/Foundation.js";
  6. import api from "@/config/api.js";
  7. import uuid from "@/utils/uuid.modified.js";
  8. let isNavigateTo = false;
  9. const urlMap = {};
  10. //同一个接口,最短请求间隔
  11. const minDuration = 300;
  12. const tooManyRequest = 'TooManyRequest';
  13. const ignoreMessages = ['/mp/v1/push/msg/orderChargeTaskOnceMsg'];
  14. function cleanStorage() {
  15. uni.showToast({
  16. title: "你的登录状态已过期,请重新登录",
  17. icon: "none",
  18. duration: 1500,
  19. });
  20. if (uni.showLoading()) {
  21. uni.hideLoading();
  22. }
  23. storage.setHasLogin(false);
  24. storage.setAccessToken("");
  25. storage.setRefreshToken("");
  26. console.log("清空token");
  27. storage.setUuid("");
  28. storage.setUserInfo({});
  29. if (!isNavigateTo) {
  30. isNavigateTo = true;
  31. // 防抖处理跳转
  32. // #ifdef MP-WEIXIN || MP-ALIPAY
  33. uni.navigateTo({
  34. url: "/pages/passport/mpLogin",
  35. });
  36. // #endif
  37. // #ifndef MP-WEIXIN || MP-ALIPAY
  38. uni.navigateTo({
  39. url: "/pages/passport/login",
  40. });
  41. // #endif
  42. }
  43. }
  44. let http = new Request();
  45. http.setConfig((config) => {
  46. // 没有uuid创建
  47. if (!storage.getUuid()) {
  48. storage.setUuid(uuid.v1());
  49. }
  50. /* 设置全局配置 */
  51. config.baseURL = api.common;
  52. // config.headers['Authorization'] = 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJ1c2VyX3R5cGUiOiIwMCIsInVzZXJfaWQiOjEsImxvZ2luX3R5cGUiOiJMaW5rV2VDaGF0QVBJIiwidXNlcl9uYW1lIjoiYWRtaW4iLCJ1c2VyX2tleSI6IjU3N2Y5ODhmLWEyNDEtNDU1Yy1iYTMwLTU3MDU3YTdlNmQxOSIsImNvcnBfbmFtZSI6IuaCoOeggeenkeaKgCIsImNvcnBfaWQiOiJ3dzEwYjk2NTQwYmUwNjc4ZDYifQ.IurVYb-vOf0Qufw1gH2Fvlrh1UpB394beLfSawJRYVRTbGadQUr6qpHh_872XQJF-eQ8Mv8Li5MnhIrfUFjQww'
  53. config.validateStatus = (statusCode) => {
  54. // 不论什么状态,统一在正确中处理
  55. return true;
  56. };
  57. return config;
  58. });
  59. http.interceptors.request.use(
  60. (config) => {
  61. /* 请求之前拦截器。可以使用async await 做异步操作 */
  62. //对post和delete做限制,对同一个请求,请求间隔小于minDuration,做拦截
  63. if(['DELETE', 'POST'].includes(config.method) && ignoreMessages.indexOf(config.url) == -1){
  64. let now = Date.now()
  65. if(urlMap[config.url]){
  66. let last = urlMap[config.url];
  67. if((now - last) < minDuration){
  68. console.log('request limit: ', config.url)
  69. config.baseURL = tooManyRequest
  70. config.url = ''
  71. return config;
  72. }
  73. }
  74. urlMap[config.url] = now;
  75. }
  76. const noncecode = Foundation.randomString(8);
  77. const tm = parseInt(new Date().getTime() / 1000);
  78. const appkey = "dbkUZnQjnIsUW0n7";
  79. const app_secret = "k1E4e6ssJhk5ZIUkD1yn65NEX8ZwFCTF";
  80. // const sign = md5(noncecode + timestamp + accessToken);
  81. const sign = md5(
  82. `appkey=${appkey}&noncecode=${noncecode}&tm=${tm}${app_secret}`
  83. ).toUpperCase();
  84. const _params = {
  85. noncecode,
  86. tm,
  87. sign,
  88. appkey,
  89. };
  90. let params = config.params || {};
  91. params = {
  92. ...params,
  93. ..._params,
  94. };
  95. config.params = params;
  96. let accessToken = storage.getAccessToken();
  97. if (accessToken) {
  98. config.header.token = accessToken;
  99. }
  100. config.header = {
  101. ...config.header,
  102. uuid: storage.getUuid() || uuid.v1(),
  103. };
  104. return config;
  105. },
  106. (config) => {
  107. return Promise.reject(config);
  108. }
  109. );
  110. // 是否正在刷新的标记
  111. let isRefreshing = false;
  112. //重试队列
  113. let requests = [];
  114. // 必须使用异步函数,注意
  115. http.interceptors.response.use(
  116. async (response) => {
  117. isNavigateTo = false;
  118. /* 请求之后拦截器。可以使用async await 做异步操作 */
  119. // token存在并且token过期
  120. // if (isRefreshing && response.statusCode === 403) {
  121. // cleanStorage();
  122. // isRefreshing = false;
  123. // }
  124. let token = storage.getAccessToken();
  125. if (
  126. (token && response.statusCode === 403) ||
  127. response.data.status === 403
  128. ) {
  129. if (!isRefreshing) {
  130. console.log("旧token", token);
  131. isRefreshing = true;
  132. storage.setAccessToken("");
  133. let oldRefreshToken = storage.getRefreshToken();
  134. //调用刷新token的接口
  135. return refreshTokenFn(oldRefreshToken)
  136. .then((res) => {
  137. let { accessToken, refreshToken } = res.data.result;
  138. storage.setAccessToken(accessToken);
  139. storage.setRefreshToken(refreshToken);
  140. response.header.accessToken = `${accessToken}`;
  141. // token 刷新后将数组的方法重新执行
  142. console.log("接口队列", requests, "新token", accessToken);
  143. requests.forEach((cb) => cb(accessToken));
  144. requests = []; // 重新请求完清空
  145. return http.request(response.config);
  146. })
  147. .catch((err) => {
  148. console.log("刷新token报错" + oldRefreshToken, err);
  149. cleanStorage();
  150. return Promise.reject(err);
  151. })
  152. .finally(() => {
  153. isRefreshing = false;
  154. });
  155. } else {
  156. // 返回未执行 resolve 的 Promise
  157. return new Promise((resolve) => {
  158. // 用函数形式将 resolve 存入,等待刷新后再执行
  159. requests.push((token) => {
  160. response.header.accessToken = `${token}`;
  161. resolve(http.request(response.config));
  162. });
  163. });
  164. }
  165. // 如果当前返回没登录
  166. } else if (
  167. (!token && !storage.getRefreshToken() && response.statusCode === 403) ||
  168. response.data.code === 403
  169. ) {
  170. console.log(
  171. "没有token 以及刷新token 内容",
  172. token,
  173. storage.getRefreshToken()
  174. );
  175. cleanStorage();
  176. // 如果当前状态码为正常但是success为不正常时
  177. } else if (
  178. (response.statusCode == 200 &&
  179. response.data.code != 200 &&
  180. response.data.status != 0) ||
  181. response.statusCode == 400
  182. ) {
  183. if (response.data.message) {
  184. uni.showToast({
  185. title: response.data.message,
  186. icon: "none",
  187. duration: 1500,
  188. });
  189. }
  190. }
  191. return response;
  192. },
  193. (error) => {
  194. if(error.config.baseURL == tooManyRequest){
  195. uni.showToast({
  196. title: "不要点得太快哟",
  197. icon: "none",
  198. duration: 1500,
  199. });
  200. }
  201. return error;
  202. }
  203. );
  204. export { http };
  205. export const Method = {
  206. GET: "GET",
  207. POST: "POST",
  208. PUT: "PUT",
  209. DELETE: "DELETE",
  210. };