request.ts 7.6 KB

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