request.ts 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. var requestTask: any = null;
  50. let header: any = {};
  51. const token = global.token ? global.token : ''; //await getStorage('token')
  52. var timeZoneFormatted = getTimezone()
  53. var timeZoneName = getTimezoneName()
  54. // var timeZoneLocation = Intl.DateTimeFormat().resolvedOptions().timeZone
  55. header['content-type'] = 'application/json'
  56. header['X-Project'] = process.env.TARO_ENV == 'rn' && kIsAndroid ? 'TIME' : 'FAST'
  57. header['X-Timezone'] = encodeURIComponent(JSON.stringify({
  58. id: getTimezoneId(),
  59. name: timeZoneName ? timeZoneName : '',
  60. gmt: timeZoneFormatted
  61. }))
  62. header['X-Request-Id'] = param.data && param.data.requestId ? param.data.requestId : new Date().getTime()
  63. if (Taro.getDeviceInfo){
  64. header['X-Platform'] = Taro.getDeviceInfo().platform == 'ios' ? 'IOS' : 'ANDROID'; //IOS ANDROID
  65. }
  66. else {
  67. header['X-Platform'] = Taro.getSystemInfoSync().platform
  68. }
  69. header['X-Lang'] = process.env.TARO_ENV == 'rn' ? global.language : 'zh' //zh en
  70. if (process.env.TARO_ENV == 'weapp') {
  71. header['X-Lang'] = global.language ?? 'zh'
  72. }
  73. header['X-Client-Type'] = process.env.TARO_ENV == 'rn' ? 'APP' : 'WX_APP' //WX_APP APP
  74. header['X-Client-Version'] = process.env.TARO_ENV == 'rn' ? kIsAndroid ? ANDROID_VERSION : APP_VERSION : WX_VERSION
  75. header['X-Day'] = dayjs().format('YYYYMMDD')
  76. header['X-Timestamp'] = new Date().getTime()
  77. if (token.length > 0) {
  78. header['Authorization'] = `Bearer ${token}`;
  79. }
  80. // header['Authorization'] = `Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJmYXN0IiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImIzNWJmMjFiMjc0ZmVhOWJkN2Y2ZjQzMGUxNDY4ZjQxIiwidHlwIjoiQmVhcmVyIiwic2Vzc2lvbl9zdGF0ZSI6IjFhZWE1M2UxN2ExNWJjZmZkZjc3ZGNhYWI5Zjc4MmNkIiwibmlja25hbWUiOiLnp4B-WGl1IiwiaWF0IjoxNzMzNTY4OTU5LCJleHAiOjIwNDkxMDE3NTl9.QoBTixnIHNx26alD5HKzzO441qOAlWMrmOMzprT99Mg`
  81. const timer = setTimeout(() => {
  82. requestTask && requestTask.abort();
  83. console.log('timeout');
  84. if (retryCount < kRetryCount) {
  85. // Retry the request
  86. console.log(`Retrying request (${retryCount + 1}/2)...`);
  87. retryCount++;
  88. performRequest(resolve, reject);
  89. return;
  90. }
  91. if (process.env.TARO_ENV == 'rn' && (param.data as any).showAlert) {
  92. showAlert({
  93. title: 'error',
  94. content: global.language == 'en' ? 'Posting failed. Please check your network.' : '操作失败,请检查网络',
  95. showCancel: false
  96. })
  97. } else {
  98. if (global.language == 'en') {
  99. ToastUtil.getInstance().showToast(method == 'GET' ?
  100. 'Network connection failed. Please check your network.' :
  101. 'Posting failed. Please check your network.');
  102. }
  103. else {
  104. ToastUtil.getInstance().showToast(method == 'GET' ? '网络连接失败,请检查网络' : '操作失败,请检查网络');
  105. }
  106. }
  107. reject('timeout');
  108. }, kTimeout);
  109. // var requestData;
  110. // if (data && data.length>0){
  111. // requestData = JSON.parse(JSON.stringify(data));
  112. // requestData.remove('showAlert')
  113. // }
  114. debugger
  115. requestTask = Taro.request({
  116. url: url,
  117. method: method,
  118. header: header,
  119. timeout: kTimeout,
  120. data: data || {},
  121. success: (response: Resp | { [key: string]: any }) => {
  122. debugger
  123. clearTimeout(timer);
  124. const { statusCode, data } = response;
  125. if (statusCode != 200) {
  126. console.log(response)
  127. }
  128. if (statusCode >= 200 && statusCode < 300) {
  129. //正常数据返回
  130. var resp = {} as T;
  131. if (response.data) {
  132. resp = response.data as T;
  133. }
  134. resolve(resp);
  135. } else if (statusCode == 401) {
  136. // global.postBtnUpdateStatus('idle')
  137. //未登录或挤下线处理
  138. if (process.env.TARO_ENV == 'weapp') {
  139. Taro.stopPullDownRefresh()
  140. }
  141. else if (process.env.TARO_ENV == 'rn') {
  142. if (url.indexOf('login/password') != -1) {
  143. reject(data);
  144. return;
  145. }
  146. }
  147. if (global.dispatch) {
  148. global.dispatch(logoutSuccess());
  149. }
  150. if (global.dispatch2) {
  151. global.dispatch2(logoutSuccess());
  152. }
  153. } else if (statusCode == 500 && response.data.error_code == 'WX_STEP_PARSE_FAIL') {
  154. //单独对计步第一次请求失败处理
  155. resolve(response.data);
  156. } else {
  157. //通用错误处理
  158. if (statusCode == 502) {
  159. if (process.env.TARO_ENV == 'rn' && (param.data as any).showAlert) {
  160. showAlert({
  161. title: 'error',
  162. content: global.language == 'en' ? 'Server is busy now. Please try again later.' : '服务器正忙, 请您稍后再试。',
  163. showCancel: false
  164. })
  165. }
  166. else {
  167. Taro.showToast({
  168. icon: 'none',
  169. title: global.language == 'en' ? 'Server is busy now. Please try again later.' : '服务器正忙, 请您稍后再试。',
  170. });
  171. }
  172. }
  173. else {
  174. if (response.data.error_code == 'BIZ_FAIL') {
  175. return;
  176. }
  177. if (process.env.TARO_ENV == 'rn' && (param.data as any).showAlert) {
  178. showAlert({
  179. title: 'error',
  180. content: data.error_message,
  181. showCancel: false
  182. })
  183. }
  184. else {
  185. Taro.showToast({
  186. icon: 'none',
  187. title: data.error_message,
  188. });
  189. }
  190. }
  191. reject(data);
  192. }
  193. },
  194. fail: err => {
  195. debugger
  196. if ((err as any).statusCode >= 200 && (err as any).statusCode < 300) {
  197. clearTimeout(timer);
  198. resolve()
  199. return;
  200. }
  201. // global.postBtnUpdateStatus('idle')
  202. // console.log('oppsu');
  203. // clearTimeout(timer);
  204. // reject(err);
  205. },
  206. });
  207. }
  208. return new Promise<T>((resolve, reject) => {
  209. performRequest(resolve, reject);
  210. });
  211. }