| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 |
- import { ArrayList, HashMap } from '@kit.ArkTS';
- import http from '@ohos.net.http';
- import { LogHelper } from '../../../../Index';
- import { SZYXLocalStorageHelper } from '../utils/SZYXLocalStorageHelper';
- import { SZYXLocalStorageKeys } from '../utils/SZYXLocalStorageKeys';
- import { HttpHelperX, HttpParamsForm, HttpParamsGet, HttpParamsPost, HttpParamsUpload } from './HttpHelperX';
- import { BusinessError } from '@kit.BasicServicesKit';
- import { image } from '@kit.ImageKit';
- type AnyResult = object | string | number | boolean | null | undefined;
- interface Waiters {
- resolve: (v: AnyResult) => void;
- reject: (e: Error) => void;
- }
- interface PendingRequest {
- http?: http.HttpRequest
- waiters: Array<Waiters>
- seq: number
- }
- export class HttpHelper {
- private static instance: HttpHelper | null = null
- // 单例模式
- static get() {
- // 判断系统是否已经有单例了
- if (HttpHelper.instance === null) {
- HttpHelper.instance = new HttpHelper()
- }
- return HttpHelper.instance
- }
- //请求中队列
- private httpHandlerList = new HashMap<string, http.HttpRequest>();
- // 并发白名单,这个名单里面的api,重复请求不会取消
- private concurrentList = new ArrayList<string>();
- private pendingMap = new HashMap<string, PendingRequest>();
- private seqGen = 0;
- constructor() {
- SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
- SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength, this.httpHandlerList.length)
- try {
- this.concurrentList.clear()
- } catch (error) {
- }
- }
- /**
- * 添加并发白名单
- * @param apiNo
- */
- public addConcurrent(apiNo?: string) {
- if (!apiNo) {
- return
- }
- try {
- if (this.concurrentList.getIndexOf(apiNo) === -1) {
- this.concurrentList.add(apiNo)
- }
- } catch (error) {
- }
- }
- public addConcurrents(apiNo: string[]) {
- for (let apiNoElement of apiNo) {
- try {
- if (this.concurrentList.getIndexOf(apiNoElement) === -1) {
- this.concurrentList.add(apiNoElement)
- }
- } catch (error) {
- }
- }
- }
- public removeConcurrent(apiNo: string) {
- try {
- if (this.concurrentList.getIndexOf(apiNo) !== -1) {
- this.concurrentList.remove(apiNo)
- }
- } catch (error) {
- }
- }
- public removeConcurrents(apiNo: string[]) {
- for (let apiNoElement of apiNo) {
- try {
- if (this.concurrentList.getIndexOf(apiNoElement) !== -1) {
- this.concurrentList.remove(apiNoElement)
- }
- } catch (error) {
- }
- }
- }
- /**
- * postJson请求
- * @param url url地址
- * @param headers
- * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
- * @returns
- */
- public postJson<T>(params: HttpParamsPost, apiNo?: string, showLog?: boolean): Promise<T> {
- return new Promise<T>((resolve, reject) => {
- let httpRequest = http.createHttp();
- const key = apiNo ?? params.url
- const pending = this.setHandler(key, httpRequest, {
- resolve: (v: AnyResult) => resolve(v as T),
- reject: (e: Error) => reject(e)
- })
- const header = HttpHelperX.getHeaders("application/json;charset=UTF-8", params.headers)
- if (showLog) {
- LogHelper.debug(`postJson:${apiNo}\n`, JSON.stringify(params))
- }
- httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
- method: http.RequestMethod.POST,
- connectTimeout: 60000,
- readTimeout: 60000,
- header: header,
- extraData: params.data,
- usingCache: false,
- }).then((data: http.HttpResponse) => {
- const latest = this.pendingMap.get(key)
- if (showLog && (!pending || (latest && latest.seq === pending.seq))) {
- LogHelper.debug(`${apiNo}:\n ${data.result as string}`)
- LogHelper.print(data)
- }
- if (data.responseCode === 200) {
- const result = (typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T
- if (!pending) {
- resolve(result)
- } else {
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- const result1 = result as AnyResult
- latest.waiters.forEach(w => w.resolve(result1))
- }
- } else {
- const err: Error = new Error()
- err.name = data.responseCode.toString()
- err.message = '服务异常'
- if (!pending) {
- reject(err)
- } else {
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- latest.waiters.forEach(w => w.reject(err))
- }
- }
- }).catch((err: Error) => {
- let e = err
- if (err.message === 'Failed writing received data to disk/application') {
- e.name = 'cancel'
- e.message = err.message
- }
- if (!pending) {
- LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
- reject(e)
- } else {
- const latest = this.pendingMap.get(key)
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
- latest.waiters.forEach(w => w.reject(e))
- }
- }).finally(() => {
- if (pending) {
- const latest = this.pendingMap.get(key)
- if (latest && latest.seq === pending.seq) {
- this.pendingMap.remove(key)
- this.httpHandlerList.remove(key)
- }
- } else {
- this.httpHandlerList.remove(key)
- }
- SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
- SZYXLocalStorageHelper.storage.setOrCreate(
- SZYXLocalStorageKeys.HttpHandlerListLength,
- this.httpHandlerList.length
- )
- })
- })
- }
- setHandler(key: string, httpRequest: http.HttpRequest, waiters: Waiters): PendingRequest | null {
- // 白名单:完全绕过
- if (this.concurrentList.getIndexOf(key) !== -1) {
- return null
- }
- if (this.seqGen > 99999) {
- this.seqGen = 0
- }
- const seq = ++this.seqGen
- let pending = this.pendingMap.get(key)
- if (!pending) {
- pending = {
- waiters: [waiters],
- seq,
- http: httpRequest
- }
- this.pendingMap.set(key, pending)
- } else {
- // cancel 旧请求
- const h = pending.http
- pending = {
- waiters: [...pending.waiters, waiters],
- seq,
- http: httpRequest
- }
- this.pendingMap.set(key, pending)
- h?.destroy()
- }
- this.httpHandlerList.set(key, httpRequest)
- SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
- SZYXLocalStorageHelper.storage.setOrCreate(
- SZYXLocalStorageKeys.HttpHandlerListLength,
- this.httpHandlerList.length
- )
- return pending
- }
- /**
- * postForm请求
- * @param url url地址
- * @param headers
- * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
- * @returns
- */
- public postForm<T>(params: HttpParamsForm, apiNo?: string, showLog?: boolean): Promise<T> {
- return new Promise<T>((resolve, reject) => {
- let httpRequest = http.createHttp();
- const key = apiNo ?? params.url
- const pending = this.setHandler(key, httpRequest, {
- resolve: (v: AnyResult) => resolve(v as T),
- reject: (e: Error) => reject(e)
- })
- const header = HttpHelperX.getHeaders("application/x-www-form-urlencoded;charset=UTF-8", params.headers)
- let data = HttpHelperX.getContent(params.data)
- if (showLog) {
- LogHelper.debug(`postForm:${apiNo}\n`, JSON.stringify(params))
- }
- httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
- method: http.RequestMethod.POST,
- connectTimeout: 20000,
- readTimeout: 20000,
- header: header,
- usingCache: false,
- extraData: data ? encodeURI(data) : undefined
- })
- .then((data: http.HttpResponse) => {
- const latest = this.pendingMap.get(key)
- if (showLog && (!pending || (latest && latest.seq === pending.seq))) {
- LogHelper.debug(`${apiNo}:\n ${data.result as string}`)
- LogHelper.print(data)
- }
- if (data.responseCode === 200) {
- const result = (typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T
- if (!pending) {
- resolve(result)
- } else {
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- const result1 = result as AnyResult
- latest.waiters.forEach(w => w.resolve(result1))
- }
- } else {
- const err: Error = new Error()
- err.name = data.responseCode.toString()
- err.message = '服务异常'
- if (!pending) {
- reject(err)
- } else {
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- latest.waiters.forEach(w => w.reject(err))
- }
- }
- }).catch((err: Error) => {
- let e = err
- if (err.message === 'Failed writing received data to disk/application') {
- e.name = 'cancel'
- e.message = err.message
- }
- if (!pending) {
- LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
- reject(e)
- } else {
- const latest = this.pendingMap.get(key)
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
- latest.waiters.forEach(w => w.reject(e))
- }
- }).finally(() => {
- if (pending) {
- const latest = this.pendingMap.get(key)
- if (latest && latest.seq === pending.seq) {
- this.pendingMap.remove(key)
- this.httpHandlerList.remove(key)
- }
- } else {
- this.httpHandlerList.remove(key)
- }
- SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
- SZYXLocalStorageHelper.storage.setOrCreate(
- SZYXLocalStorageKeys.HttpHandlerListLength,
- this.httpHandlerList.length
- )
- });
- });
- }
- /**
- * get请求
- * @param url url地址
- * @param data 请求参数
- * @param headers
- * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
- * @returns
- */
- public get<T>(params: HttpParamsGet, apiNo?: string, showLog?: boolean): Promise<T> {
- return new Promise<T>((resolve, reject) => {
- let httpRequest = http.createHttp();
- const key = apiNo ?? params.url
- const pending = this.setHandler(key, httpRequest, {
- resolve: (v: AnyResult) => resolve(v as T),
- reject: (e: Error) => reject(e)
- })
- if (showLog) {
- LogHelper.debug(`GET:${apiNo}\n`, HttpHelperX.getUrl(params.url, params.query) + '\n',
- JSON.stringify(params.headers))
- }
- httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
- method: http.RequestMethod.GET,
- connectTimeout: 20000,
- readTimeout: 20000,
- header: params.headers,
- usingCache: false,
- // extraData: params.data
- })
- .then((data: http.HttpResponse) => {
- const latest = this.pendingMap.get(key)
- if (showLog && (!pending || (latest && latest.seq === pending.seq))) {
- LogHelper.debug(`${apiNo}:\n ${data.result as string}`)
- LogHelper.print(data)
- }
- if (data.responseCode === 200) {
- const result = (typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T
- if (!pending) {
- resolve(result)
- } else {
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- const result1 = result as AnyResult
- latest.waiters.forEach(w => w.resolve(result1))
- }
- } else {
- const err: Error = new Error()
- err.name = data.responseCode.toString()
- err.message = '服务异常'
- if (!pending) {
- reject(err)
- } else {
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- latest.waiters.forEach(w => w.reject(err))
- }
- }
- }).catch((err: Error) => {
- let e = err
- if (err.message === 'Failed writing received data to disk/application') {
- e.name = 'cancel'
- e.message = err.message
- }
- if (!pending) {
- LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
- reject(e)
- } else {
- const latest = this.pendingMap.get(key)
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
- latest.waiters.forEach(w => w.reject(e))
- }
- }).finally(() => {
- if (pending) {
- const latest = this.pendingMap.get(key)
- if (latest && latest.seq === pending.seq) {
- this.pendingMap.remove(key)
- this.httpHandlerList.remove(key)
- }
- } else {
- this.httpHandlerList.remove(key)
- }
- SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
- SZYXLocalStorageHelper.storage.setOrCreate(
- SZYXLocalStorageKeys.HttpHandlerListLength,
- this.httpHandlerList.length
- )
- });
- });
- }
- /**
- * postJson请求
- * @param url url地址
- * @param headers
- * @param apiNo 请求标识,取消请求或者去重使用|考虑做自动重试使用
- * @returns
- */
- public upload<T>(params: HttpParamsUpload, apiNo?: string, showLog?: boolean): Promise<T> {
- return new Promise<T>((resolve, reject) => {
- let httpRequest = http.createHttp();
- const key = apiNo ?? params.url
- const pending = this.setHandler(key, httpRequest, {
- resolve: (v: AnyResult) => resolve(v as T),
- reject: (e: Error) => reject(e)
- })
- if (showLog) {
- LogHelper.debug(`postJson:${apiNo}\n`, JSON.stringify(params))
- }
- httpRequest.on("dataSendProgress", (data: http.DataSendProgressInfo) => {
- if (showLog) {
- LogHelper.debug(`${apiNo}:\n${JSON.stringify(data)}`)
- }
- params.onProgress && params.onProgress(data.sendSize, data.totalSize)
- });
- httpRequest.request(HttpHelperX.getUrl(params.url, params.query), {
- method: http.RequestMethod.POST,
- connectTimeout: 20000,
- readTimeout: 20000,
- header: HttpHelperX.getHeaders("multipart/form-data", params.headers),
- usingCache: false,
- multiFormDataList: params.data,
- })
- .then((data: http.HttpResponse) => {
- const latest = this.pendingMap.get(key)
- if (showLog && (!pending || (latest && latest.seq === pending.seq))) {
- LogHelper.debug(`${apiNo}:\n ${data.result as string}`)
- LogHelper.print(data)
- }
- if (data.responseCode === 200) {
- const result = (typeof data.result === 'string' ? JSON.parse(data.result) : data.result) as T
- if (!pending) {
- resolve(result)
- } else {
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- const result1 = result as AnyResult
- latest.waiters.forEach(w => w.resolve(result1))
- }
- } else {
- const err: Error = new Error()
- err.name = data.responseCode.toString()
- err.message = '服务异常'
- if (!pending) {
- reject(err)
- } else {
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- latest.waiters.forEach(w => w.reject(err))
- }
- }
- }).catch((err: Error) => {
- let e = err
- if (err.message === 'Failed writing received data to disk/application') {
- e.name = 'cancel'
- e.message = err.message
- }
- if (!pending) {
- LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
- reject(e)
- } else {
- const latest = this.pendingMap.get(key)
- if (!latest || latest.seq !== pending.seq) {
- return
- }
- LogHelper.error(JSON.stringify({ err: err, url: params.url, }))
- latest.waiters.forEach(w => w.reject(e))
- }
- }).finally(() => {
- if (pending) {
- const latest = this.pendingMap.get(key)
- if (latest && latest.seq === pending.seq) {
- this.pendingMap.remove(key)
- this.httpHandlerList.remove(key)
- }
- } else {
- this.httpHandlerList.remove(key)
- }
- SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
- SZYXLocalStorageHelper.storage.setOrCreate(
- SZYXLocalStorageKeys.HttpHandlerListLength,
- this.httpHandlerList.length
- )
- });
- });
- }
- clearHttp() {
- for (let handler of this.httpHandlerList.keys()) {
- this.cancel(handler)
- }
- }
- cancel(apiNo: string) {
- try {
- if (this.httpHandlerList.hasKey(apiNo)) {
- this.httpHandlerList.get(apiNo).destroy()
- this.httpHandlerList.remove(apiNo)
- SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerList, this.httpHandlerList)
- SZYXLocalStorageHelper.storage.setOrCreate(SZYXLocalStorageKeys.HttpHandlerListLength,
- this.httpHandlerList.length)
- }
- } catch (error) {
- }
- }
- downloadImage(url: string): Promise<image.ImageSource> {
- return new Promise<image.ImageSource>((resolve, reject) => {
- http.createHttp()
- .request(url, (error: BusinessError, data: http.HttpResponse) => {
- if (error) {
- reject(error)
- return
- }
- if (data.result instanceof ArrayBuffer) {
- let imageData: ArrayBuffer = data.result as ArrayBuffer;
- let imageSource: image.ImageSource = image.createImageSource(imageData);
- resolve(imageSource)
- } else {
- reject(new Error('下载图片失败'))
- }
- })
- })
- }
- }
|