axios-miniprogram/src/core/adapter.ts

271 lines
6.4 KiB
TypeScript
Raw Normal View History

2021-05-21 14:26:22 +08:00
import {
assert,
isEmptyArray,
isPlainObject,
isPlatform,
isUndefined,
revisePlatformApiNames,
throwError,
} from '../utils';
import {
AxiosProgressCallback,
AxiosRequestConfig,
AxiosRequestData,
AxiosRequestFormData,
AxiosRequestHeaders,
AxiosResponse,
AxiosResponseError,
} from './Axios';
export type AdapterRequestMethod =
| 'OPTIONS'
| 'GET'
| 'HEAD'
| 'POST'
| 'PUT'
| 'DELETE'
| 'TRACE'
| 'CONNECT';
export type AdapterRequestType = 'request' | 'download' | 'upload';
export interface AxiosAdapterRequestConfig extends AxiosRequestConfig {
type: AdapterRequestType;
method: AdapterRequestMethod;
url: string;
success(response: AxiosResponse): void;
fail(error: AxiosResponseError): void;
}
export interface AxiosAdapterRequestOptions extends AxiosAdapterRequestConfig {
header?: AxiosRequestHeaders;
success(response: any): void;
fail(error: any): void;
}
export interface AxiosAdapterUploadOptions extends AxiosAdapterRequestOptions {
filePath: string;
name: string;
fileName: string;
fileType: 'image' | 'video' | 'audio';
hideLoading?: boolean;
formData?: AxiosRequestData;
}
export interface AxiosAdapterDownloadOptions
extends AxiosAdapterRequestOptions {
filePath?: string;
fileName?: string;
}
export interface AxiosAdapterRequest {
(config: AxiosAdapterRequestOptions): AxiosAdapterTask | void;
}
export interface AxiosAdapterUpload {
(config: AxiosAdapterUploadOptions): AxiosAdapterTask | void;
}
export interface AxiosAdapterDownload {
(config: AxiosAdapterDownloadOptions): AxiosAdapterTask | void;
}
export interface AxiosPlatform {
request: AxiosAdapterRequest;
upload: AxiosAdapterUpload;
download: AxiosAdapterDownload;
}
export interface AxiosAdapterTask {
abort?(): void;
onProgressUpdate?(callback: AxiosProgressCallback): void;
offProgressUpdate?(callback: AxiosProgressCallback): void;
}
export interface AxiosAdapter {
(config: AxiosAdapterRequestConfig): AxiosAdapterTask | void;
}
export function createAdapter(platform: AxiosPlatform): AxiosAdapter {
assert(isPlainObject(platform), 'platform 需要是一个 Object 类型');
assert(
isPlatform(platform),
'platform.request 与 platform.download 和 platform.upload 需要是一个 Function 类型',
);
2021-05-24 21:25:07 +08:00
function transformResult(result: any): void {
if (!isUndefined(result.statusCode)) {
result.status = result.statusCode;
delete result.statusCode;
2021-05-21 14:26:22 +08:00
}
2021-05-24 21:25:07 +08:00
if (isUndefined(result.status)) {
result.status = isUndefined(result.data) ? 400 : 200;
2021-05-21 14:26:22 +08:00
}
2021-05-24 21:25:07 +08:00
if (!isUndefined(result.header)) {
result.headers = result.header;
delete result.header;
2021-05-21 14:26:22 +08:00
}
2021-05-24 21:25:07 +08:00
if (isUndefined(result.headers)) {
result.headers = {};
2021-05-21 14:26:22 +08:00
}
2021-05-24 21:25:07 +08:00
if (!isUndefined(result.errMsg)) {
result.statusText = result.errMsg;
delete result.errMsg;
2021-05-21 14:26:22 +08:00
}
2021-05-24 21:25:07 +08:00
if (isUndefined(result.statusText)) {
result.statusText =
result.status === 200
2021-05-21 14:26:22 +08:00
? 'OK'
2021-05-24 21:25:07 +08:00
: result.status === 400
2021-05-21 14:26:22 +08:00
? 'Bad Adapter'
: '';
}
}
2021-05-24 21:25:07 +08:00
function injectDownloadData(response: any): void {
2021-05-21 14:26:22 +08:00
if (!isPlainObject(response.data)) {
response.data = {};
}
if (!isUndefined(response.tempFilePath)) {
response.data.tempFilePath = response.tempFilePath;
delete response.tempFilePath;
}
if (!isUndefined(response.apFilePath)) {
response.data.tempFilePath = response.apFilePath;
delete response.apFilePath;
}
if (!isUndefined(response.filePath)) {
response.data.filePath = response.filePath;
delete response.filePath;
}
}
function requestAdapter(
request: AxiosAdapterRequest,
config: AxiosAdapterRequestConfig,
): AxiosAdapterTask | void {
const options = Object.assign({}, config, {
header: config.headers,
success(response: any): void {
2021-05-24 21:25:07 +08:00
transformResult(response);
2021-05-21 14:26:22 +08:00
config.success(response);
},
fail(error: any): void {
2021-05-24 21:25:07 +08:00
transformResult(error);
2021-05-21 14:26:22 +08:00
config.fail(error);
},
});
return request(options);
}
function uploadAdapter(
upload: AxiosAdapterUpload,
config: AxiosAdapterRequestConfig,
): AxiosAdapterTask | void {
const {
fileName,
filePath,
fileType,
hideLoading,
...formData
} = config.data as AxiosRequestFormData;
const options = Object.assign({}, config, {
header: config.headers,
name: fileName,
fileName: fileName,
filePath,
fileType: fileType ?? 'image',
hideLoading,
formData,
success(response: any): void {
2021-05-24 21:25:07 +08:00
transformResult(response);
2021-05-21 14:26:22 +08:00
config.success(response);
},
fail(error: any): void {
2021-05-24 21:25:07 +08:00
transformResult(error);
2021-05-21 14:26:22 +08:00
config.fail(error);
},
});
return upload(options);
}
function downloadAdapter(
download: AxiosAdapterDownload,
config: AxiosAdapterRequestConfig,
): AxiosAdapterTask | void {
const options = Object.assign({}, config, {
header: config.headers,
filePath: config.params?.filePath,
fileName: config.params?.fileName,
success(response: any): void {
2021-05-24 21:25:07 +08:00
injectDownloadData(response);
transformResult(response);
2021-05-21 14:26:22 +08:00
config.success(response);
},
fail(error: any): void {
2021-05-24 21:25:07 +08:00
transformResult(error);
2021-05-21 14:26:22 +08:00
config.fail(error);
},
});
return download(options);
}
return function adapterDefault(
config: AxiosAdapterRequestConfig,
): AxiosAdapterTask | void {
switch (config.type) {
case 'request':
return requestAdapter(platform.request, config);
case 'upload':
return uploadAdapter(platform.upload, config);
case 'download':
return downloadAdapter(platform.download, config);
default:
throwError(`无法识别的请求类型 ${config.type}`);
}
};
}
export function getAdapterDefault(): AxiosAdapter | undefined {
const tryGetPlatforms = [
() => uni,
() => wx,
() => my,
() => swan,
() => tt,
() => qq,
() => qh,
() => ks,
() => dd,
];
let platform;
while (!isEmptyArray(tryGetPlatforms) && !isPlatform(platform)) {
try {
const tryGetPlatform = tryGetPlatforms.shift()!;
if (isPlainObject((platform = tryGetPlatform()))) {
platform = revisePlatformApiNames(platform);
}
} catch (err) {
// 避免出现异常导致程序被终止
}
}
if (!isPlatform(platform)) {
return;
}
return createAdapter(platform);
}