request.ts 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. import { logoutSuccess } from "@/store/user";
  2. import ToastUtil from "@/utils/toast_utils";
  3. import Taro from "@tarojs/taro";
  4. import { useDispatch } from "react-redux";
  5. import dayjs from 'dayjs'
  6. import { APP_VERSION, WX_VERSION, ANDROID_VERSION } from "./api";
  7. import { getTimezone, getTimezoneId, getTimezoneName, kIsAndroid } from "@/utils/tools";
  8. import showAlert from "@/components/basic/Alert";
  9. const utc = require('dayjs/plugin/utc')
  10. const timezone = require('dayjs/plugin/timezone')
  11. const PROJECT_NAME = 'TIME' //FAST
  12. dayjs.extend(utc)
  13. dayjs.extend(timezone)
  14. interface RequestParam {
  15. url: string;
  16. method: 'POST' | 'GET' | 'DELETE' | 'PUT';
  17. data?: Record<string, any>;
  18. showAlert?: boolean;
  19. }
  20. interface Resp {
  21. statusCode?: number;
  22. header?: any;
  23. data?: any;
  24. errMsg?: string;
  25. };
  26. async function getStorage(key: string) {
  27. try {
  28. const res = await Taro.getStorage({ key });
  29. return res.data;
  30. } catch {
  31. return '';
  32. }
  33. }
  34. //X-Language:语言,X-Device-Id:设备唯一码,X-Platform:小程序/android/ios,X-Location:地区,X-Device:登录设备
  35. // header['X-Language'] = ''
  36. // header['X-Device-Id'] = ''
  37. // header['X-Platform'] = ''
  38. // header['X-Location'] = ''
  39. // header['X-Device'] = ''
  40. // header['X-Time-Zone-Id'] = Intl.DateTimeFormat().resolvedOptions().timeZone
  41. // header['Authorization'] = 'Bearer ' + wx.getStorageSync('token');
  42. // header['Authorization'] = 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhY2NvdW50Iiwic3ViIjoiMmQ5OWNlYzI0ZDFlMzE0Y2U1MjhlODM4MWMzYzk0MzgiLCJpc3MiOiJDT0RFUEFBUy5DT00iLCJuaWNrbmFtZSI6IueOi-a4nSIsInR5cCI6IkJlYXJlciIsInNlc3Npb25fc3RhdGUiOiIyN2RjNmU4ZDdjMWU1MTVmNDQwNzVjZTFlODk2ZmUzNCIsImV4cCI6MTcxNjY0Mzk5MSwiaWF0IjoxNjg1MDIxNTkxfQ.fmFj0OVNRzjLkdebSyGJyk8EScPJFpDiz0L25W35zoA'
  43. export async function request<T>(param: RequestParam): Promise<T> {
  44. const kTimeout = 8000;
  45. const kRetryCount = 2;
  46. let retryCount = 0;
  47. function performRequest(resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) {
  48. const { url, method, data } = param;
  49. console.log(url)
  50. var requestTask: any = null;
  51. let header: any = {};
  52. const token = global.token ? global.token : ''; //await getStorage('token')
  53. var timeZoneFormatted = getTimezone()
  54. var timeZoneName = getTimezoneName()
  55. // var timeZoneLocation = Intl.DateTimeFormat().resolvedOptions().timeZone
  56. header['content-type'] = 'application/json'
  57. header['X-Project'] = process.env.TARO_ENV == 'rn' && kIsAndroid?'TIME':'FAST'
  58. header['X-Timezone'] = encodeURIComponent(JSON.stringify({
  59. id: getTimezoneId(),
  60. name: timeZoneName ? timeZoneName : '',
  61. gmt: timeZoneFormatted
  62. }))
  63. header['X-Platform'] = Taro.getDeviceInfo().platform == 'ios' ? 'IOS' : 'ANDROID'; //IOS ANDROID
  64. header['X-Lang'] = process.env.TARO_ENV == 'rn' ? global.language : 'zh' //zh en
  65. if (process.env.TARO_ENV == 'weapp'){
  66. header['X-Lang'] = global.language??'zh'
  67. }
  68. header['X-Client-Type'] = process.env.TARO_ENV == 'rn' ? 'APP' : 'WX_APP' //WX_APP APP
  69. header['X-Client-Version'] = process.env.TARO_ENV == 'rn' ? kIsAndroid ? ANDROID_VERSION : APP_VERSION : WX_VERSION
  70. header['X-Day'] = dayjs().format('YYYYMMDD')
  71. header['X-Timestamp'] = new Date().getTime()
  72. if (token.length > 0) {
  73. header['Authorization'] = `Bearer ${token}`;
  74. // header['Authorization'] = 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhY2NvdW50Iiwic3ViIjoiMTE0Nzg0NGE5NDIyODk1MmE5Zjc2OTdjYWJjYmU3Y2UiLCJpc3MiOiJmYXN0Iiwibmlja25hbWUiOiJGYXN0ZXIiLCJ0eXAiOiJCZWFyZXIiLCJzZXNzaW9uX3N0YXRlIjoiZWE5NTQ1Y2VkNThlNzgzNTA1MWRjZTY0ODEwMzQ4ZmQiLCJleHAiOjE3NDk3MDA3MTYsImlhdCI6MTcxODE2NDcxN30.yrh-xAJhmfG-CueyCsToW-X4Dx043DYhk5DiE0E4eNk';
  75. // header['Authorization'] = 'Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhY2NvdW50Iiwic3ViIjoiMjZkOGE1YTg0MDMyYmExN2Q4NDk3MTlkNTljNGY1NzgiLCJpc3MiOiJmYXN0Iiwibmlja25hbWUiOiJCSyIsInR5cCI6IkJlYXJlciIsInNlc3Npb25fc3RhdGUiOiI1ZDU2NTkzYmNjNWFmNzM0OWNlZTMwZjlkNGYzMWIyMCIsImV4cCI6MTc0ODE3MDg5NSwiaWF0IjoxNzE2NjM0ODk1fQ.uaRm2vSNCX8fkFS63Oe-WNWIDHG_cRM-nQ5EGyUMaBg';
  76. }
  77. const timer = setTimeout(() => {
  78. requestTask && requestTask.abort();
  79. console.log('timeout');
  80. if (retryCount < kRetryCount) {
  81. // Retry the request
  82. console.log(`Retrying request (${retryCount + 1}/2)...`);
  83. retryCount++;
  84. performRequest(resolve, reject);
  85. return;
  86. }
  87. if (process.env.TARO_ENV == 'rn' && (param.data as any).showAlert) {
  88. showAlert({
  89. title: 'error',
  90. content: global.language == 'en' ? 'Posting failed. Please check your network.' : '操作失败,请检查网络',
  91. showCancel: false
  92. })
  93. } else {
  94. if (global.language == 'en') {
  95. ToastUtil.getInstance().showToast(method == 'GET' ?
  96. 'Network connection failed. Please check your network.' :
  97. 'Posting failed. Please check your network.');
  98. }
  99. else {
  100. ToastUtil.getInstance().showToast(method == 'GET' ? '网络连接失败,请检查网络' : '操作失败,请检查网络');
  101. }
  102. }
  103. reject('timeout');
  104. }, kTimeout);
  105. // var requestData;
  106. // if (data && data.length>0){
  107. // requestData = JSON.parse(JSON.stringify(data));
  108. // requestData.remove('showAlert')
  109. // }
  110. requestTask = Taro.request({
  111. url: url,
  112. method: method,
  113. header: header,
  114. timeout: kTimeout,
  115. data: data || {},
  116. success: (response: Resp | { [key: string]: any }) => {
  117. clearTimeout(timer);
  118. const { statusCode, data } = response;
  119. if (statusCode != 200) {
  120. console.log(response)
  121. }
  122. if (statusCode >= 200 && statusCode < 300) {
  123. //正常数据返回
  124. var resp = {} as T;
  125. if (response.data) {
  126. resp = response.data as T;
  127. }
  128. resolve(resp);
  129. } else if (statusCode == 401) {
  130. // global.postBtnUpdateStatus('idle')
  131. //未登录或挤下线处理
  132. if (process.env.TARO_ENV == 'weapp') {
  133. Taro.stopPullDownRefresh()
  134. }
  135. else if (process.env.TARO_ENV == 'rn') {
  136. if (url.indexOf('login/password') != -1) {
  137. reject(data);
  138. return;
  139. }
  140. }
  141. if (global.dispatch) {
  142. global.dispatch(logoutSuccess());
  143. }
  144. } else if (statusCode == 500 && response.data.error_code == 'WX_STEP_PARSE_FAIL') {
  145. //单独对计步第一次请求失败处理
  146. resolve(response.data);
  147. } else {
  148. //通用错误处理
  149. if (statusCode == 502) {
  150. if (process.env.TARO_ENV == 'rn' && (param.data as any).showAlert) {
  151. showAlert({
  152. title: 'error',
  153. content: global.language == 'en' ? 'Server is busy now. Please try again later.' : '服务器正忙, 请您稍后再试。',
  154. showCancel: false
  155. })
  156. }
  157. else {
  158. Taro.showToast({
  159. icon: 'none',
  160. title: global.language == 'en' ? 'Server is busy now. Please try again later.' : '服务器正忙, 请您稍后再试。',
  161. });
  162. }
  163. }
  164. else {
  165. if (response.data.error_code == 'BIZ_FAIL') {
  166. return;
  167. }
  168. if (process.env.TARO_ENV == 'rn' && (param.data as any).showAlert) {
  169. showAlert({
  170. title: 'error',
  171. content: data.error_message,
  172. showCancel: false
  173. })
  174. }
  175. else {
  176. Taro.showToast({
  177. icon: 'none',
  178. title: data.error_message,
  179. });
  180. }
  181. }
  182. reject(data);
  183. }
  184. },
  185. fail: err => {
  186. if ((err as any).statusCode >= 200 && (err as any).statusCode < 300) {
  187. clearTimeout(timer);
  188. resolve()
  189. return;
  190. }
  191. // global.postBtnUpdateStatus('idle')
  192. // console.log('oppsu');
  193. // clearTimeout(timer);
  194. // reject(err);
  195. },
  196. });
  197. }
  198. return new Promise<T>((resolve, reject) => {
  199. performRequest(resolve, reject);
  200. });
  201. }