request.ts 7.6 KB

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