axios-miniprogram/src/core/adapter.ts

296 lines
7.1 KiB
TypeScript
Raw Normal View History

2021-05-21 14:26:22 +08:00
import {
isEmptyArray,
2021-05-25 21:46:27 +08:00
isFunction,
2021-05-21 14:26:22 +08:00
isPlainObject,
2021-05-26 20:21:37 +08:00
isString,
2021-05-21 14:26:22 +08:00
isUndefined,
2021-05-25 23:17:29 +08:00
} from '../helpers/is';
import { assert, throwError } from '../helpers/utils';
2021-05-21 14:26:22 +08:00
import {
AxiosProgressCallback,
AxiosRequestConfig,
AxiosRequestData,
AxiosRequestFormData,
AxiosRequestHeaders,
AxiosResponse,
AxiosResponseError,
} from './Axios';
2021-05-30 14:11:09 +08:00
export type AxiosAdapterRequestType = 'request' | 'download' | 'upload';
2021-05-26 20:21:37 +08:00
2021-05-30 14:11:09 +08:00
export type AxiosAdapterRequestMethod =
2021-05-21 14:26:22 +08:00
| 'OPTIONS'
| 'GET'
| 'HEAD'
| 'POST'
| 'PUT'
| 'DELETE'
| 'TRACE'
| 'CONNECT';
export interface AxiosAdapterRequestConfig extends AxiosRequestConfig {
2021-05-30 14:11:09 +08:00
type: AxiosAdapterRequestType;
method: AxiosAdapterRequestMethod;
2021-05-21 14:26:22 +08:00
url: string;
success(response: AxiosResponse): void;
fail(error: AxiosResponseError): void;
}
2021-05-30 14:11:09 +08:00
export interface AxiosAdapterBaseOptions extends AxiosAdapterRequestConfig {
2021-05-21 14:26:22 +08:00
header?: AxiosRequestHeaders;
success(response: any): void;
fail(error: any): void;
}
2021-05-30 14:11:09 +08:00
export interface AxiosAdapterUploadOptions extends AxiosAdapterBaseOptions {
2021-05-21 14:26:22 +08:00
filePath: string;
name: string;
fileName: string;
fileType: 'image' | 'video' | 'audio';
hideLoading?: boolean;
formData?: AxiosRequestData;
}
2021-05-30 14:11:09 +08:00
export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions {
2021-05-21 14:26:22 +08:00
filePath?: string;
fileName?: string;
}
export interface AxiosAdapterRequest {
2021-05-30 14:11:09 +08:00
(config: AxiosAdapterBaseOptions): AxiosAdapterTask | void;
2021-05-21 14:26:22 +08:00
}
export interface AxiosAdapterUpload {
(config: AxiosAdapterUploadOptions): AxiosAdapterTask | void;
}
export interface AxiosAdapterDownload {
(config: AxiosAdapterDownloadOptions): AxiosAdapterTask | void;
}
2021-06-04 09:57:36 +08:00
2021-05-21 14:26:22 +08:00
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;
}
2021-05-25 23:17:29 +08:00
export function isPlatform(value: any): value is AxiosPlatform {
return (
isPlainObject(value) &&
isFunction(value.request) &&
isFunction(value.upload) &&
isFunction(value.download)
);
}
export function revisePlatformApiNames(platform: AnyObject): AxiosPlatform {
return {
request: platform.request ?? platform.httpRequest,
upload: platform.upload ?? platform.uploadFile,
download: platform.download ?? platform.downloadFile,
};
}
2021-05-21 14:26:22 +08:00
export function createAdapter(platform: AxiosPlatform): AxiosAdapter {
2021-05-25 21:46:27 +08:00
assert(isPlainObject(platform), 'platform 需要是一个 object');
assert(isFunction(platform.request), 'platform.request 需要是一个 function');
assert(isFunction(platform.upload), 'platform.upload 需要是一个 function');
2021-05-21 14:26:22 +08:00
assert(
2021-05-25 21:46:27 +08:00
isFunction(platform.download),
'platform.download 需要是一个 function',
2021-05-21 14:26:22 +08:00
);
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-30 14:11:09 +08:00
function transformOptions(
config: AxiosAdapterRequestConfig,
): AxiosAdapterBaseOptions {
return {
...config,
header: config.headers,
success(response: any): void {
transformResult(response);
config.success(response);
},
fail(error: any): void {
transformResult(error);
config.fail(error);
},
};
}
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;
}
}
2021-05-30 14:11:09 +08:00
function callRequest(
2021-05-21 14:26:22 +08:00
request: AxiosAdapterRequest,
2021-05-30 14:11:09 +08:00
baseOptions: AxiosAdapterBaseOptions,
2021-05-21 14:26:22 +08:00
): AxiosAdapterTask | void {
2021-05-30 14:11:09 +08:00
return request(baseOptions);
2021-05-21 14:26:22 +08:00
}
2021-05-30 14:11:09 +08:00
function callUpload(
2021-05-21 14:26:22 +08:00
upload: AxiosAdapterUpload,
2021-05-30 14:11:09 +08:00
baseOptions: AxiosAdapterBaseOptions,
2021-05-21 14:26:22 +08:00
): AxiosAdapterTask | void {
2021-05-26 20:21:37 +08:00
assert(
2021-05-30 14:11:09 +08:00
isPlainObject(baseOptions.data),
'上传文件时 data 需要是一个 object',
);
assert(
isString(baseOptions.data!.fileName),
2021-05-26 20:21:37 +08:00
'上传文件时 data.fileName 需要是一个 string',
);
assert(
2021-05-30 14:11:09 +08:00
isString(baseOptions.data!.filePath),
2021-05-26 20:21:37 +08:00
'上传文件时 data.filePath 需要是一个 string',
);
2021-05-21 14:26:22 +08:00
const {
fileName,
filePath,
fileType,
hideLoading,
...formData
2021-05-30 14:11:09 +08:00
} = baseOptions.data as AxiosRequestFormData;
const options = {
...baseOptions,
2021-05-21 14:26:22 +08:00
name: fileName,
fileName: fileName,
filePath,
fileType: fileType ?? 'image',
hideLoading,
formData,
2021-05-30 14:11:09 +08:00
};
2021-05-21 14:26:22 +08:00
return upload(options);
}
2021-05-30 14:11:09 +08:00
function callDownload(
2021-05-21 14:26:22 +08:00
download: AxiosAdapterDownload,
2021-05-30 14:11:09 +08:00
baseOptions: AxiosAdapterBaseOptions,
2021-05-21 14:26:22 +08:00
): AxiosAdapterTask | void {
2021-05-30 14:11:09 +08:00
const options = {
...baseOptions,
filePath: baseOptions.params?.filePath,
fileName: baseOptions.params?.fileName,
2021-05-21 14:26:22 +08:00
success(response: any): void {
2021-05-24 21:25:07 +08:00
injectDownloadData(response);
2021-05-30 14:11:09 +08:00
baseOptions.success(response);
2021-05-21 14:26:22 +08:00
},
2021-05-30 14:11:09 +08:00
};
2021-05-21 14:26:22 +08:00
return download(options);
}
return function adapterDefault(
config: AxiosAdapterRequestConfig,
): AxiosAdapterTask | void {
2021-05-30 14:11:09 +08:00
const baseOptions = transformOptions(config);
2021-05-21 14:26:22 +08:00
switch (config.type) {
case 'request':
2021-05-30 14:11:09 +08:00
return callRequest(platform.request, baseOptions);
2021-05-21 14:26:22 +08:00
case 'upload':
2021-05-30 14:11:09 +08:00
return callUpload(platform.upload, baseOptions);
2021-05-21 14:26:22 +08:00
case 'download':
2021-05-30 14:11:09 +08:00
return callDownload(platform.download, baseOptions);
2021-05-21 14:26:22 +08:00
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);
}