138 lines
4.7 KiB
TypeScript
138 lines
4.7 KiB
TypeScript
import Taro, { UploadTask } from '@tarojs/taro';
|
|
|
|
import { HttpError } from '@/http/error';
|
|
import { safeJsonParse } from '@/utils/common';
|
|
|
|
import { API, BASE_URL } from './api';
|
|
import { HTTP_STATUS, RESPONSE_ERROR_CODE } from './constant';
|
|
import interceptors from './interceptor';
|
|
import { IRequestResponse } from './type';
|
|
import { isTokenExpired, refreshToken } from './utils';
|
|
|
|
interface IRequestOption<T = BL.Anything> extends Taro.request.Option<T> {
|
|
contentType?: 'application/json' | 'application/x-www-form-urlencoded';
|
|
blRetryTime?: number;
|
|
}
|
|
|
|
interface IUploadOption extends Taro.uploadFile.Option {
|
|
blRetryTime?: number;
|
|
onProgress?: UploadTask.OnProgressUpdateCallback;
|
|
}
|
|
|
|
interceptors.forEach(interceptor => Taro.addInterceptor(interceptor));
|
|
|
|
class Http {
|
|
private throwHttpError = (resp: Taro.request.SuccessCallbackResult<IRequestResponse>) => {
|
|
const { statusCode, data } = resp;
|
|
const errorCode = data?.code || 'null';
|
|
const errorMsg = data?.msg || 'unknown';
|
|
const traceId = data?.traceId;
|
|
console.error(
|
|
`http request fail, httpCode: ${statusCode}, errorCode: ${errorCode}, errorMsg: ${errorMsg}, traceId: ${traceId}`
|
|
);
|
|
throw new HttpError('request fail', errorCode, errorMsg, traceId);
|
|
};
|
|
|
|
private isNeedLoginError = (
|
|
options: { blRetryTime?: number },
|
|
resp: Taro.request.SuccessCallbackResult<IRequestResponse>
|
|
) => {
|
|
if (options.blRetryTime && options.blRetryTime >= 3) {
|
|
return false;
|
|
}
|
|
const { statusCode, data } = resp;
|
|
return statusCode !== HTTP_STATUS.SUCCESS && data?.code === RESPONSE_ERROR_CODE.NEED_LOGIN;
|
|
};
|
|
|
|
private uploadFile = (options: IUploadOption) => {
|
|
const { onProgress, ...option } = options;
|
|
let offProgressUpdate: (() => void) | null = null;
|
|
return new Promise((resolve, reject) => {
|
|
option.success = resolve;
|
|
option.fail = reject;
|
|
const task = Taro.uploadFile(option);
|
|
onProgress && task.onProgressUpdate(onProgress);
|
|
onProgress && (offProgressUpdate = () => task.offProgressUpdate(onProgress));
|
|
})
|
|
.then((resp: Taro.uploadFile.SuccessCallbackResult) => {
|
|
if (resp.statusCode === 200) {
|
|
return safeJsonParse(resp.data.replace(/\uFEFF/g, ''));
|
|
} else if (this.isNeedLoginError(option, resp as Taro.request.SuccessCallbackResult)) {
|
|
option.blRetryTime = (option.blRetryTime || 0) + 1;
|
|
return refreshToken().then(() => this.uploadFile(option));
|
|
} else {
|
|
this.throwHttpError(resp as Taro.request.SuccessCallbackResult);
|
|
}
|
|
})
|
|
.finally(() => offProgressUpdate?.());
|
|
};
|
|
|
|
private request = (option: IRequestOption) => {
|
|
return new Promise((resolve, reject) => {
|
|
option.success = resolve;
|
|
option.fail = reject;
|
|
Taro.request(option);
|
|
}).then((resp: Taro.request.SuccessCallbackResult) => {
|
|
if (resp.statusCode === HTTP_STATUS.SUCCESS) {
|
|
return resp.data;
|
|
} else if (this.isNeedLoginError(option, resp)) {
|
|
option.blRetryTime = (option.blRetryTime || 0) + 1;
|
|
return refreshToken().then(() => this.request(option));
|
|
} else {
|
|
this.throwHttpError(resp);
|
|
}
|
|
});
|
|
};
|
|
|
|
private baseUpload = (params: IUploadOption) => {
|
|
const { url, ...otherParams } = params;
|
|
const option: IUploadOption = {
|
|
// 默认超时时间三分钟
|
|
timeout: 1000 * 60 * 3,
|
|
...otherParams,
|
|
blRetryTime: 0,
|
|
url: url.startsWith('http') ? url : BASE_URL + url,
|
|
header: { 'content-type': 'multipart/form-data' },
|
|
};
|
|
|
|
return this.uploadFile(option);
|
|
};
|
|
|
|
private baseRequest = (params: IRequestOption, method: Taro.request.Option['method'] = 'GET') => {
|
|
const { url, data, ...otherParams } = params;
|
|
const contentType = params.contentType || 'application/json';
|
|
const option: IRequestOption = {
|
|
...otherParams,
|
|
blRetryTime: 0,
|
|
url: BASE_URL + url,
|
|
data,
|
|
method: method,
|
|
header: { 'content-type': contentType /*'user-Id': '588002047871053824' */ },
|
|
};
|
|
return this.request(option);
|
|
};
|
|
|
|
async init(inviteCode?: string) {
|
|
if (isTokenExpired()) {
|
|
await refreshToken(inviteCode);
|
|
}
|
|
}
|
|
|
|
get = <T = BL.Anything>(url: API, params?: Omit<IRequestOption<T>, 'url'>): Promise<T> => {
|
|
const option = { url, ...params };
|
|
return this.baseRequest(option);
|
|
};
|
|
|
|
post = <T = BL.Anything>(url: API, params?: Omit<IRequestOption<T>, 'url'>): Promise<T> => {
|
|
const option = { url, ...params };
|
|
return this.baseRequest(option, 'POST');
|
|
};
|
|
|
|
upload = <T = BL.Anything>(url: API | string, params?: Omit<IUploadOption, 'url'>): Promise<T> => {
|
|
const option = { url, ...params } as IUploadOption;
|
|
return this.baseUpload(option);
|
|
};
|
|
}
|
|
|
|
export default new Http();
|