request.ts 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. import { common } from '../utils';
  2. import { useSmallProgramLogin } from '../hook';
  3. import store from '../store';
  4. import { REQUEST_CONFIG } from '../config';
  5. let _app;
  6. /**
  7. * HTTP POST 请求封装
  8. * complete:是否成功失败都往下执行
  9. */
  10. const httpPost = (url: string, data: any, options: any = {}, complete = undefined) => {
  11. let has = getApp().globalData.accountInfo.miniProgram.envVersion != 'develop'; // 如果不等于开发版本,默认启用请求加密
  12. let querData: any = {};
  13. // 判断当前请求接口不需要加密请求
  14. if (common.isNotEmpty(getApp().globalData.noNeedSecretKeyApiArr)) {
  15. for (let i of getApp().globalData.noNeedSecretKeyApiArr) {
  16. if (url.indexOf(i) != '-1') {
  17. has = false;
  18. break;
  19. }
  20. }
  21. }
  22. // 新增判断请求的url 如果不存在callApiJSON,callApi.do请求,全部不加密(后续callApi.do接口前端也统一加密)
  23. if (url.indexOf('callApiJSON') == -1 && url.indexOf('callApi.do') == -1) {
  24. has = false;
  25. }
  26. let showLoading = true;
  27. if (options != undefined && options.showLoading != undefined) {
  28. showLoading = options.showLoading;
  29. }
  30. if (showLoading) {
  31. common.showLoading();
  32. }
  33. let header: any = {
  34. 'content-type': 'application/json',
  35. token: store.state.token,
  36. 'call-appId': uni.getStorageSync('frontEndConfig').fixedAppjsGlobalData.appId,
  37. };
  38. // 如果has 为true 代表当前请求接口需要加密 且获取的加密秘钥不为空
  39. if (has && common.isNotEmpty(getApp().globalData.apiSecretKey)) {
  40. (header.appId = 'KASIET_alismaillpro'),
  41. (querData.data = common.desEncrypt(JSON.stringify(data), getApp().globalData.apiSecretKey));
  42. }
  43. if (options) {
  44. const extOptions = [
  45. 'showLoading', // 显示加载中
  46. 'onChunkReceived', // 分块传输监听
  47. 'timeout', // 超时时间, 默认取/app.json里的networkTimeout配置
  48. 'responseType', // 响应结果
  49. ];
  50. Object.keys(options).forEach((key) => {
  51. if (!extOptions.includes(key)) {
  52. header[key] = options[key];
  53. }
  54. });
  55. }
  56. return new Promise((resolve, reject) => {
  57. const enableChunked = options && typeof options.onChunkReceived == 'function';
  58. const requestOptions: any = {
  59. url: url,
  60. data: common.isEmpty(querData) ? data : querData,
  61. method: 'POST',
  62. header: header,
  63. enableChunked: enableChunked, // 新增分块数据
  64. success(res) {
  65. if (showLoading) {
  66. common.hideLoading();
  67. }
  68. if (!complete) {
  69. if (options && options.construction) {
  70. resolve({ data: { Data: res.data, RespCode: 10000 } });
  71. } else {
  72. resolve(res);
  73. }
  74. }
  75. },
  76. fail(error) {
  77. if (showLoading) {
  78. common.hideLoading();
  79. }
  80. if (!complete) {
  81. reject(error);
  82. }
  83. console.error(error);
  84. common.showToast(`连接超时,请重试`);
  85. },
  86. complete(res) {
  87. if (complete) {
  88. resolve(res);
  89. }
  90. },
  91. };
  92. if (options && options.timeout != undefined && options.timeout != null) {
  93. requestOptions.timeout = options.timeout;
  94. }
  95. if (options && options.responseType != undefined && options.responseType != null) {
  96. requestOptions.responseType = options.responseType;
  97. }
  98. const wxRequest = uni.request(requestOptions);
  99. if (enableChunked) {
  100. wxRequest.onChunkReceived(options.onChunkReceived);
  101. }
  102. });
  103. };
  104. /**
  105. * 微信请求post方法封装
  106. * url
  107. * data 以对象的格式传入
  108. * 后端返回 401 token超时时,会重新发起调用登陆
  109. */
  110. const doPost = async (url: string, data: any, options: any = {}, complete = undefined) => {
  111. const response = httpPost(url, data, options, complete);
  112. let loginAgain = false;
  113. await response.then((resp: any) => {
  114. if (resp.data.RespCode == 401) {
  115. loginAgain = true;
  116. }
  117. });
  118. // token未超时,直接返回
  119. if (!loginAgain) {
  120. return response;
  121. }
  122. // token超时时,调用接口重新登录
  123. if (uni.getStorageSync('isCall') != 1) {
  124. // 防止页面并发调用登录接口
  125. uni.setStorageSync('isCall', 1);
  126. uni.setStorageSync('data_expiration', 0);
  127. console.log("login timeout")
  128. // 获取登录失败轮询次数,,默认5次
  129. let retry = getApp().globalData.retryNum;
  130. while (retry > 0) {
  131. await useSmallProgramLogin(_app).then((resp: any) => {
  132. if (resp.data.RespCode != '10000') {
  133. // 登录失败,需轮询,次数减一
  134. retry--;
  135. } else {
  136. // 登录成功
  137. retry = 0;
  138. // uni.clearStorageSync()
  139. }
  140. });
  141. if (retry != 0) {
  142. // 需要重试时,先休眠300毫秒
  143. await sleep(300);
  144. }
  145. }
  146. }
  147. // 接口调用重试次数,默认判断5次,每次间隔500毫秒
  148. let retry = getApp().globalData.retryNum;
  149. while (retry > 0) {
  150. if (uni.getStorageSync('isCall') != 1) {
  151. // 如果已经重新登录成功,返回重新请求接口结果
  152. return httpPost(url, data, options);
  153. } else {
  154. // 还未登录成功,休眠500毫秒再判断
  155. await sleep(500);
  156. retry--;
  157. }
  158. }
  159. // 重试5次后,再次重新发起请求
  160. return httpPost(url, data, options);
  161. };
  162. /**
  163. * 微信请求get方法封装
  164. * url
  165. * data 以对象的格式传入
  166. * 后端返回 401 token超时时,会重新发起调用登陆
  167. */
  168. const doGet = async (url: string, data: any, options: any = {}) => {
  169. const response = httpGet(url, data, options);
  170. let loginAgain = false;
  171. await response.then((resp: any) => {
  172. if (resp.data.RespCode == 401) {
  173. loginAgain = true;
  174. }
  175. });
  176. // token未超时,直接返回
  177. if (!loginAgain) {
  178. return response;
  179. }
  180. // token超时时,调用接口重新登录
  181. if (uni.getStorageSync('isCall') != 1) {
  182. // 防止页面并发调用登录接口
  183. uni.setStorageSync('isCall', 1);
  184. uni.setStorageSync('data_expiration', 0);
  185. // 获取登录失败轮询次数,默认5次
  186. let retry = getApp().globalData.retryNum;
  187. while (retry > 0) {
  188. await useSmallProgramLogin(_app).then((resp: any) => {
  189. if (resp.data.RespCode != '10000') {
  190. // 登录失败,需轮询,次数减一
  191. retry--;
  192. } else {
  193. // 登录成功
  194. retry = 0;
  195. }
  196. });
  197. if (retry != 0) {
  198. // 需要重试时,先休眠300毫秒
  199. await sleep(300);
  200. }
  201. }
  202. }
  203. // 接口调用重试次数,默认判断5次,每次间隔500毫秒
  204. let retry = getApp().globalData.retryNum;
  205. while (retry > 0) {
  206. if (uni.getStorageSync('isCall') != 1) {
  207. // 如果已经重新登录成功,返回重新请求接口结果
  208. return httpGet(url, data, options);
  209. } else {
  210. // 还未登录成功,休眠500毫秒再判断
  211. await sleep(500);
  212. retry--;
  213. }
  214. }
  215. // 重试5次后,再次重新发起请求
  216. return httpGet(url, data, options);
  217. };
  218. // 新增 httpGet 基础方法
  219. const httpGet = (url: string, data: any, options: any = {}) => {
  220. let showLoading = true;
  221. if (options != undefined && options.showLoading != undefined) {
  222. showLoading = options.showLoading;
  223. }
  224. if (showLoading) {
  225. common.showLoading();
  226. }
  227. let header = {
  228. 'content-type': 'application/json',
  229. token: getApp().globalData.token || uni.getStorageSync('token'),
  230. 'call-appId': uni.getStorageSync('frontEndConfig').fixedAppjsGlobalData.appId,
  231. };
  232. if (options) {
  233. Object.keys(options).forEach((key) => {
  234. if (key != 'showLoading') {
  235. header[key] = options[key];
  236. }
  237. });
  238. }
  239. return new Promise((resolve, reject) => {
  240. uni.request({
  241. url: url,
  242. data: data,
  243. method: 'GET',
  244. header: header,
  245. success(res) {
  246. if (showLoading) {
  247. common.hideLoading();
  248. }
  249. if (options && options.construction) {
  250. resolve({ data: { Data: res.data, RespCode: 10000 } });
  251. } else {
  252. resolve(res);
  253. }
  254. },
  255. fail(error) {
  256. if (showLoading) {
  257. common.hideLoading();
  258. }
  259. reject(error);
  260. common.showToast(`连接超时,请重试`);
  261. },
  262. });
  263. });
  264. };
  265. //模拟线程休眠,需配合 async和await使用
  266. const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
  267. export default {
  268. doPost,
  269. doGet,
  270. };