HttpHelper.ets 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. import { ArrayList, HashMap } from '@kit.ArkTS';
  2. import http from '@ohos.net.http';
  3. import { LogHelper } from '../../../../Index';
  4. import { SZYXLocalStorageHelper } from '../utils/SZYXLocalStorageHelper';
  5. import { SZYXLocalStorageKeys } from '../utils/SZYXLocalStorageKeys';
  6. import { HttpHelperX, HttpParamsForm, HttpParamsGet, HttpParamsPost, HttpParamsUpload } from './HttpHelperX';
  7. import { BusinessError } from '@kit.BasicServicesKit';
  8. import { image } from '@kit.ImageKit';
  9. export class HttpHelper {
  10. private static instance: HttpHelper | null = null
  11. // 单例模式
  12. static get() {
  13. // 判断系统是否已经有单例了
  14. if (HttpHelper.instance === null) {
  15. HttpHelper.instance = new HttpHelper()
  16. }
  17. return HttpHelper.instance
  18. }
  19. //请求中队列
  20. private httpHandlerList = new HashMap<string, http.HttpRequest>();
  21. // 并发白名单,这个名单里面的api,重复请求不会取消
  22. private concurrentList = new ArrayList<string>();
  23. constructor() {
  24. this.httpHandlerList = new HashMap<string, http.HttpRequest>();
  25. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  26. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length)
  27. this.concurrentList.clear()
  28. }
  29. /**
  30. * 添加并发白名单
  31. * @param apiNo
  32. */
  33. public addConcurrent(apiNo?: string) {
  34. if (!apiNo) {
  35. return
  36. }
  37. if (this.concurrentList.getIndexOf(apiNo) === -1) {
  38. this.concurrentList.add(apiNo)
  39. }
  40. }
  41. public addConcurrents(apiNo: string[]) {
  42. for (let apiNoElement of apiNo) {
  43. if (this.concurrentList.getIndexOf(apiNoElement) === -1) {
  44. this.concurrentList.add(apiNoElement)
  45. }
  46. }
  47. }
  48. public removeConcurrent(apiNo: string) {
  49. if (this.concurrentList.getIndexOf(apiNo) !== -1) {
  50. this.concurrentList.remove(apiNo)
  51. }
  52. }
  53. public removeConcurrents(apiNo: string[]) {
  54. for (let apiNoElement of apiNo) {
  55. if (this.concurrentList.getIndexOf(apiNoElement) !== -1) {
  56. this.concurrentList.remove(apiNoElement)
  57. }
  58. }
  59. }
  60. /**
  61. * postJson请求
  62. * @param url url地址
  63. * @param headers
  64. * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
  65. * @returns
  66. */
  67. public postJson<T>(params: HttpParamsPost, apiNo?: string, showLog?: boolean): Promise<T> {
  68. return new Promise<T>((resolve, reject) => {
  69. let httpRequest = http.createHttp();
  70. this.setHandler(apiNo ?? params.url, httpRequest)
  71. const header = HttpHelperX.getHeaders("application/json;charset=UTF-8", params.headers)
  72. if (showLog) {
  73. LogHelper.debug(`postJson:${apiNo}\n`, JSON.stringify(params))
  74. }
  75. httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
  76. method: http.RequestMethod.POST,
  77. connectTimeout: 20000,
  78. readTimeout: 20000,
  79. header: header,
  80. extraData: params.data,
  81. usingCache: false,
  82. })
  83. .then((data: http.HttpResponse) => {
  84. if (showLog) {
  85. LogHelper.debug(`${apiNo}:\n ${data.result as string}`)
  86. LogHelper.print(data)
  87. }
  88. if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
  89. this.httpHandlerList.remove(apiNo ?? params.url)
  90. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  91. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  92. this.httpHandlerList.length)
  93. }
  94. if (data.responseCode === 200) {
  95. resolve((typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T)
  96. } else {
  97. const err: Error = new Error()
  98. err.name = data.responseCode.toString()
  99. err.message = '服务异常'
  100. reject(err)
  101. }
  102. }).catch((err: Error) => {
  103. LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
  104. if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
  105. this.httpHandlerList.remove(apiNo ?? params.url)
  106. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  107. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  108. this.httpHandlerList.length)
  109. }
  110. if (err.message === 'Failed writing received data to disk/application') {
  111. const error: Error = new Error()
  112. error.name = 'cancel'
  113. error.message = err.message
  114. reject(error)
  115. } else {
  116. reject(err)
  117. }
  118. });
  119. });
  120. }
  121. setHandler(key: string, httpRequest: http.HttpRequest) {
  122. if (this.concurrentList.getIndexOf(key) === -1 &&
  123. this.httpHandlerList.hasKey(key)) {
  124. this.httpHandlerList.get(key).destroy()
  125. this.httpHandlerList.remove(key)
  126. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  127. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  128. this.httpHandlerList.length)
  129. }
  130. if (this.concurrentList.getIndexOf(key) === -1) {
  131. this.httpHandlerList.set(key, httpRequest)
  132. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  133. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  134. this.httpHandlerList.length)
  135. }
  136. }
  137. /**
  138. * postForm请求
  139. * @param url url地址
  140. * @param headers
  141. * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
  142. * @returns
  143. */
  144. public postForm<T>(params: HttpParamsForm, apiNo?: string, showLog?: boolean): Promise<T> {
  145. return new Promise<T>((resolve, reject) => {
  146. let httpRequest = http.createHttp();
  147. this.setHandler(apiNo ?? params.url, httpRequest)
  148. const header = HttpHelperX.getHeaders("application/x-www-form-urlencoded;charset=UTF-8", params.headers)
  149. let data = HttpHelperX.getContent(params.data)
  150. if (showLog) {
  151. LogHelper.debug(`postForm:${apiNo}\n`, JSON.stringify(params))
  152. }
  153. httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
  154. method: http.RequestMethod.POST,
  155. connectTimeout: 20000,
  156. readTimeout: 20000,
  157. header: header,
  158. usingCache: false,
  159. extraData: data ? encodeURI(data) : undefined
  160. })
  161. .then((data: http.HttpResponse) => {
  162. if (showLog) {
  163. LogHelper.debug(`${apiNo}:\n ${data.result as string}`)
  164. LogHelper.print(data)
  165. }
  166. if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
  167. this.httpHandlerList.remove(apiNo ?? params.url)
  168. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  169. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  170. this.httpHandlerList.length)
  171. }
  172. if (data.responseCode === 200) {
  173. resolve((typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T)
  174. } else {
  175. const err: Error = new Error()
  176. err.name = data.responseCode.toString()
  177. err.message = '服务异常'
  178. reject(err)
  179. }
  180. }).catch((err: Error) => {
  181. LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
  182. if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
  183. this.httpHandlerList.remove(apiNo ?? params.url)
  184. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  185. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  186. this.httpHandlerList.length)
  187. }
  188. if (err.message === 'Failed writing received data to disk/application') {
  189. const error: Error = new Error()
  190. error.name = 'cancel'
  191. error.message = err.message
  192. reject(error)
  193. } else {
  194. reject(err)
  195. }
  196. });
  197. });
  198. }
  199. /**
  200. * get请求
  201. * @param url url地址
  202. * @param data 请求参数
  203. * @param headers
  204. * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
  205. * @returns
  206. */
  207. public get<T>(params: HttpParamsGet, apiNo?: string, showLog?: boolean): Promise<T> {
  208. return new Promise<T>((resolve, reject) => {
  209. let httpRequest = http.createHttp();
  210. this.setHandler(apiNo ?? params.url, httpRequest)
  211. if (showLog) {
  212. LogHelper.debug(`GET:${apiNo}\n`, HttpHelperX.getUrl(params.url, params.query) + '\n',
  213. JSON.stringify(params.headers))
  214. }
  215. httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
  216. method: http.RequestMethod.GET,
  217. connectTimeout: 20000,
  218. readTimeout: 20000,
  219. header: params.headers,
  220. usingCache: false,
  221. // extraData: params.data
  222. })
  223. .then((data: http.HttpResponse) => {
  224. if (showLog) {
  225. LogHelper.debug(`${apiNo}:\n${data.result as string}`)
  226. LogHelper.print(data)
  227. }
  228. if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
  229. this.httpHandlerList.remove(apiNo ?? params.url)
  230. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  231. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  232. this.httpHandlerList.length)
  233. }
  234. if (data.responseCode === 200) {
  235. if (typeof data.result === 'string') {
  236. resolve(JSON.parse(data.result) as T)
  237. } else {
  238. resolve(data.result as T)
  239. }
  240. } else {
  241. const err: Error = new Error()
  242. err.name = data.responseCode.toString()
  243. err.message = '服务异常'
  244. reject(err)
  245. }
  246. }).catch((err: Error) => {
  247. LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
  248. if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
  249. this.httpHandlerList.remove(apiNo ?? params.url)
  250. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  251. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  252. this.httpHandlerList.length)
  253. }
  254. if (err.message === 'Failed writing received data to disk/application') {
  255. const error: Error = new Error()
  256. error.name = 'cancel'
  257. error.message = err.message
  258. reject(error)
  259. } else {
  260. reject(err)
  261. }
  262. });
  263. });
  264. }
  265. /**
  266. * postJson请求
  267. * @param url url地址
  268. * @param headers
  269. * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
  270. * @returns
  271. */
  272. public upload<T>(params: HttpParamsUpload, apiNo?: string, showLog?: boolean): Promise<T> {
  273. return new Promise<T>((resolve, reject) => {
  274. let httpRequest = http.createHttp();
  275. this.setHandler(apiNo ?? params.url, httpRequest)
  276. if (showLog) {
  277. LogHelper.debug(`postJson:${apiNo}\n`, JSON.stringify(params))
  278. }
  279. httpRequest.on("dataSendProgress", (data: http.DataSendProgressInfo) => {
  280. if (showLog) {
  281. LogHelper.debug(`${apiNo}:\n${JSON.stringify(data)}`)
  282. }
  283. params.onProgress && params.onProgress(data.sendSize, data.totalSize)
  284. });
  285. httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
  286. method: http.RequestMethod.POST,
  287. connectTimeout: 20000,
  288. readTimeout: 20000,
  289. header: HttpHelperX.getHeaders("multipart/form-data", params.headers),
  290. usingCache: false,
  291. multiFormDataList: params.data,
  292. })
  293. .then((data: http.HttpResponse) => {
  294. if (showLog) {
  295. LogHelper.debug(`${apiNo}:\n ${data.result as string}`)
  296. LogHelper.print(data)
  297. }
  298. if (data.responseCode === 200) {
  299. resolve((typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T)
  300. } else {
  301. const err: Error = new Error()
  302. err.name = data.responseCode.toString()
  303. err.message = '服务异常'
  304. reject(err)
  305. }
  306. }).catch((err: Error) => {
  307. LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
  308. if (err.message === 'Failed writing received data to disk/application') {
  309. const error: Error = new Error()
  310. error.name = 'cancel'
  311. error.message = err.message
  312. reject(error)
  313. } else {
  314. reject(err)
  315. }
  316. }).finally(() => {
  317. httpRequest.off("dataSendProgress");
  318. if (this.httpHandlerList.hasKey(apiNo ?? params.url)) {
  319. this.httpHandlerList.remove(apiNo ?? params.url)
  320. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  321. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  322. this.httpHandlerList.length)
  323. }
  324. });
  325. });
  326. }
  327. clearHttp() {
  328. for (let handler of this.httpHandlerList.keys()) {
  329. this.cancel(handler)
  330. }
  331. }
  332. cancel(apiNo: string) {
  333. if (this.httpHandlerList.hasKey(apiNo)) {
  334. this.httpHandlerList.get(apiNo).destroy()
  335. this.httpHandlerList.remove(apiNo)
  336. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
  337. SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
  338. this.httpHandlerList.length)
  339. }
  340. }
  341. downloadImage(url: string): Promise<image.ImageSource> {
  342. return new Promise<image.ImageSource>((resolve, reject) => {
  343. http.createHttp()
  344. .request(url, (error: BusinessError, data: http.HttpResponse) => {
  345. if (error) {
  346. reject(error)
  347. return
  348. }
  349. if (data.result instanceof ArrayBuffer) {
  350. let imageData: ArrayBuffer = data.result as ArrayBuffer;
  351. let imageSource: image.ImageSource = image.createImageSource(imageData);
  352. resolve(imageSource)
  353. } else {
  354. reject(new Error('下载图片失败'))
  355. }
  356. })
  357. })
  358. }
  359. }