refactor: 默认值的设置流程移到 request 里

pull/49/head
zjx0905 2023-04-20 13:56:17 +08:00
parent 258954afc1
commit 1867273460
6 changed files with 133 additions and 131 deletions

View File

@ -91,7 +91,7 @@ import axios from 'axios-miniprogram';
// 适配器 // 适配器
axios.defaults.adapter = (config) => { axios.defaults.adapter = (config) => {
// 可以先看看 config 都有哪些东西 // 可以先看看 config 上都有哪些属性
console.log(config); console.log(config);
// 开始适配不同类型的请求 // 开始适配不同类型的请求
@ -122,13 +122,16 @@ axios.defaults.adapter = (config) => {
success: (response) => { success: (response) => {
config.success({ config.success({
// 状态码 // 状态码
// 默认值200
status: response.statusCode, status: response.statusCode,
// 状态文本,选填,不传默认 'OK' // 状态文本
// 默认值:'OK'
statusText: 'OK', statusText: 'OK',
// 响应头 // 响应头
headers: response.header ?? {}, // 默认值:{}
headers: response.header,
// 响应数据 // 响应数据
data: response.data, data: response.data,
@ -139,13 +142,16 @@ axios.defaults.adapter = (config) => {
}, },
fail: (error) => { fail: (error) => {
config.fail({ config.fail({
// 状态码,选填,不传默认 400 // 状态码
// 默认值400
status: 400, status: 400,
// 状态文本,选填,不传默认 'Fail Adapter' // 状态文本
statusText: 'Fail Adapter', // 默认值:'Fail'
statusText: 'Fail',
// 响应头,选填,不传默认 {} // 响应头
// 默认值:{}
headers: {}, headers: {},
// 响应数据 // 响应数据
@ -171,12 +177,15 @@ axios.defaults.adapter = (config) => {
success: (response) => { success: (response) => {
config.success({ config.success({
// 状态码 // 状态码
// 默认值200
status: response.statusCode, status: response.statusCode,
// 状态文本,选填,不传默认 'OK' // 状态文本
// 默认值:'OK'
statusText: 'OK', statusText: 'OK',
// 响应头 // 响应头
// 默认值:{}
headers: response.header, headers: response.header,
// 响应数据 // 响应数据
@ -185,13 +194,16 @@ axios.defaults.adapter = (config) => {
}, },
fail: (error) => { fail: (error) => {
config.fail({ config.fail({
// 状态码,选填,不传默认 400 // 状态码
// 默认值400
status: 400, status: 400,
// 状态文本,选填,不传默认 'Fail Adapter' // 状态文本
statusText: 'Fail Adapter', // 默认值:'Fail'
statusText: 'Fail',
// 响应头,选填,不传默认 {} // 响应头
// 默认值:{}
headers: {}, headers: {},
// 响应数据 // 响应数据
@ -210,13 +222,16 @@ axios.defaults.adapter = (config) => {
success: (response) => { success: (response) => {
config.success({ config.success({
// 状态码 // 状态码
// 默认值200
status: response.statusCode, status: response.statusCode,
// 状态文本,选填,不传默认 'OK' // 状态文本
// 默认值:'OK'
statusText: 'OK', statusText: 'OK',
// 响应头 // 响应头
headers: response.header ?? {}, // 默认值:{}
headers: response.header,
// 响应数据 // 响应数据
data: { data: {
@ -227,13 +242,16 @@ axios.defaults.adapter = (config) => {
}, },
fail: (error) => { fail: (error) => {
config.fail({ config.fail({
// 状态码,选填,不传默认 400 // 状态码
// 默认值400
status: 400, status: 400,
// 状态文本,选填,不传默认 'Fail Adapter' // 状态文本
statusText: 'Fail Adapter', // 默认值:'Fail'
statusText: 'Fail',
// 响应头,选填,不传默认 {} // 响应头
// 默认值:{}
headers: {}, headers: {},
// 响应数据 // 响应数据

View File

@ -5,7 +5,6 @@
"main": "dist/axios-miniprogram.cjs.js", "main": "dist/axios-miniprogram.cjs.js",
"module": "dist/axios-miniprogram.esm.js", "module": "dist/axios-miniprogram.esm.js",
"types": "dist/axios-miniprogram.d.ts", "types": "dist/axios-miniprogram.d.ts",
"type": "module",
"files": [ "files": [
"dist" "dist"
], ],
@ -25,6 +24,7 @@
}, },
"homepage": "https://axios-miniprogram.com", "homepage": "https://axios-miniprogram.com",
"license": "MIT", "license": "MIT",
"type": "module",
"scripts": { "scripts": {
"cz": "simple-git-hooks && czg", "cz": "simple-git-hooks && czg",
"build": "esno scripts/build.ts", "build": "esno scripts/build.ts",

View File

@ -1,9 +1,4 @@
import { import { isFunction, isPlainObject } from './helpers/isTypes';
isFunction,
isPlainObject,
isString,
isUndefined,
} from './helpers/isTypes';
import { assert } from './helpers/error'; import { assert } from './helpers/error';
import { import {
AxiosProgressCallback, AxiosProgressCallback,
@ -138,8 +133,17 @@ export interface AxiosAdapterRequestConfig extends AnyObject {
* *
*/ */
export interface AxiosAdapterBaseOptions extends AxiosAdapterRequestConfig { export interface AxiosAdapterBaseOptions extends AxiosAdapterRequestConfig {
/**
* headers
*/
header?: AxiosRequestHeaders; header?: AxiosRequestHeaders;
/**
*
*/
success(response: AxiosAdapterResponse): void; success(response: AxiosAdapterResponse): void;
/**
*
*/
fail(error: AxiosAdapterResponseError): void; fail(error: AxiosAdapterResponseError): void;
} }
@ -152,6 +156,9 @@ export type AxiosAdapterRequestOptions = AxiosAdapterBaseOptions;
* *
*/ */
export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions { export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions {
/**
*
*/
filePath?: string; filePath?: string;
} }
@ -161,7 +168,17 @@ export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions {
export interface AxiosAdapterUploadOptions export interface AxiosAdapterUploadOptions
extends AxiosAdapterBaseOptions, extends AxiosAdapterBaseOptions,
AxiosRequestFormData { AxiosRequestFormData {
/**
* [ fileName name](https://open.dingtalk.com/document/orgapp/dd-upload-objects#title-ngk-rr1-eow)
*/
fileName: string; fileName: string;
/**
* |
*/
fileType?: 'image' | 'video' | 'audie';
/**
*
*/
formData?: AnyObject; formData?: AnyObject;
} }
@ -290,15 +307,42 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
function adapter( function adapter(
config: AxiosAdapterRequestConfig, config: AxiosAdapterRequestConfig,
): AxiosAdapterPlatformTask { ): AxiosAdapterPlatformTask {
const baseOptions = transformOptions(config); const options = transformOptions(config);
switch (config.type) { switch (config.type) {
case 'request': case 'request':
return processRequest(platform.request, baseOptions); return processRequest(platform.request, options);
case 'download': case 'download':
return processDownload(platform.download, baseOptions); return processDownload(platform.download, options);
case 'upload': case 'upload':
return processUpload(platform.upload, baseOptions); return processUpload(platform.upload, options);
}
}
function transformOptions(
config: AxiosAdapterRequestConfig,
): AxiosAdapterBaseOptions {
return {
...config,
success(response) {
transformResponse(response);
config.success(response);
},
fail(responseError) {
responseError.data = {
errMsg: responseError.errMsg,
errno: responseError.errno,
};
transformResponse(responseError);
config.fail(responseError);
},
};
function transformResponse(
response: AxiosAdapterResponse | AxiosAdapterResponseError,
) {
response.status = response.status ?? response.statusCode;
response.headers = response.headers ?? response.header;
clean(response, ['statusCode', 'errMsg', 'errno', 'header']);
} }
} }
@ -313,22 +357,14 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
upload: AxiosAdapterUpload, upload: AxiosAdapterUpload,
baseOptions: AxiosAdapterBaseOptions, baseOptions: AxiosAdapterBaseOptions,
): AxiosAdapterPlatformTask { ): AxiosAdapterPlatformTask {
const { name, filePath, fileType, ...formData } = const options = baseOptions as AxiosAdapterUploadOptions;
baseOptions.data as AxiosRequestFormData; const { name, filePath, fileType, ...formData } = options.data as AnyObject;
const options = {
...baseOptions, options.name = name;
name, options.fileName = name;
/** options.filePath = filePath;
* [ fileName name](https://open.dingtalk.com/document/orgapp/dd-upload-objects#title-ngk-rr1-eow) options.fileType = fileType;
*/ options.formData = formData;
fileName: name,
filePath,
/**
* |
*/
fileType,
formData,
};
return upload(options); return upload(options);
} }
@ -337,74 +373,28 @@ export function createAdapter(platform: AxiosAdapterPlatform) {
download: AxiosAdapterDownload, download: AxiosAdapterDownload,
baseOptions: AxiosAdapterBaseOptions, baseOptions: AxiosAdapterBaseOptions,
): AxiosAdapterPlatformTask { ): AxiosAdapterPlatformTask {
const options: AxiosAdapterDownloadOptions = { const options = baseOptions as AxiosAdapterDownloadOptions;
...baseOptions, const { params, success } = options;
filePath: baseOptions.params?.filePath,
success(response): void { options.filePath = params?.filePath;
injectDownloadData(response); options.success = (response) => {
baseOptions.success(response); response.data = {
}, filePath: response.filePath,
tempFilePath:
response.tempFilePath ||
// response.apFilePath 为支付宝小程序基础库小于 2.7.23 的特有属性。
response.apFilePath,
};
clean(response, ['tempFilePath', 'apFilePath', 'filePath']);
success(response);
}; };
return download(options); return download(options);
} }
function transformResponse(response: AnyObject): void { function clean(obj: AnyObject, keys: string[]) {
response.status = response.status ?? response.statusCode;
response.statusText = 'OK';
if (isUndefined(response.status)) {
response.status = 400;
response.statusText = 'Fail Adapter';
}
response.headers = response.headers ?? response.header ?? {};
if (isUndefined(response.data) && isString(response.errMsg)) {
response.data = {
errMsg: response.errMsg,
errno: response.errno,
};
}
cleanResponse(response, ['statusCode', 'errMsg', 'errno', 'header']);
}
function transformOptions(
config: AxiosAdapterRequestConfig,
): AxiosAdapterBaseOptions {
return {
...config,
header: config.headers,
success(response): void {
transformResponse(response);
config.success(response);
},
fail(error: AxiosAdapterResponseError): void {
transformResponse(error);
config.fail(error);
},
};
}
function injectDownloadData(response: AnyObject): void {
response.data = {
filePath: response.filePath,
tempFilePath:
response.tempFilePath ||
// response.apFilePath 为支付宝小程序基础库小于 2.7.23 的特有属性。
response.apFilePath,
};
cleanResponse(response, ['tempFilePath', 'apFilePath', 'filePath']);
}
/**
* response key
*/
function cleanResponse(response: AnyObject, keys: string[]) {
for (const key of keys) { for (const key of keys) {
delete response[key]; delete obj[key];
} }
} }

View File

@ -99,7 +99,7 @@ export type AxiosRequestData =
/** /**
* *
*/ */
export type AxiosResponseData = undefined | number | AxiosAdapterResponseData; export type AxiosResponseData = number | AxiosAdapterResponseData;
/** /**
* *
@ -259,7 +259,7 @@ export interface AxiosResponseError extends AnyObject {
/** /**
* *
*/ */
data?: AnyObject; data: AnyObject;
/** /**
* *
*/ */

View File

@ -56,10 +56,11 @@ export function request(config: AxiosRequestConfig) {
response.config = config; response.config = config;
response.request = adapterTask; response.request = adapterTask;
if (config.validateStatus?.(response.status) ?? true) { const { validateStatus } = config;
if (!isFunction(validateStatus) || validateStatus(response.status)) {
resolve(response); resolve(response);
} else { } else {
catchError('validate status fail', response); catchError('validate status error', response);
} }
} }
@ -67,7 +68,7 @@ export function request(config: AxiosRequestConfig) {
const responseError = baseResponseError as AxiosResponseError; const responseError = baseResponseError as AxiosResponseError;
responseError.isFail = true; responseError.isFail = true;
responseError.status = responseError.status ?? 400; responseError.status = responseError.status ?? 400;
responseError.statusText = responseError.statusText ?? 'Fail Adapter'; responseError.statusText = responseError.statusText ?? 'Fail';
responseError.headers = responseError.headers ?? {}; responseError.headers = responseError.headers ?? {};
responseError.config = config; responseError.config = config;
responseError.request = adapterTask; responseError.request = adapterTask;

View File

@ -81,9 +81,6 @@ describe('src/adapter.ts', () => {
expect(p.request.mock.calls[0][0]).toMatchInlineSnapshot(` expect(p.request.mock.calls[0][0]).toMatchInlineSnapshot(`
{ {
"fail": [Function], "fail": [Function],
"header": {
"Accept": "application/json, text/plain, */*",
},
"headers": { "headers": {
"Accept": "application/json, text/plain, */*", "Accept": "application/json, text/plain, */*",
}, },
@ -112,9 +109,6 @@ describe('src/adapter.ts', () => {
"id": 1, "id": 1,
"user": "test", "user": "test",
}, },
"header": {
"Accept": "application/json, text/plain, */*",
},
"headers": { "headers": {
"Accept": "application/json, text/plain, */*", "Accept": "application/json, text/plain, */*",
}, },
@ -132,9 +126,6 @@ describe('src/adapter.ts', () => {
{ {
"fail": [Function], "fail": [Function],
"filePath": "/path/file", "filePath": "/path/file",
"header": {
"Accept": "application/json, text/plain, */*",
},
"headers": { "headers": {
"Accept": "application/json, text/plain, */*", "Accept": "application/json, text/plain, */*",
}, },
@ -271,9 +262,12 @@ describe('src/adapter.ts', () => {
fail: (response: any) => { fail: (response: any) => {
expect(response).toMatchInlineSnapshot(` expect(response).toMatchInlineSnapshot(`
{ {
"headers": {}, "data": {
"status": 400, "errMsg": undefined,
"statusText": "Fail Adapter", "errno": undefined,
},
"headers": undefined,
"status": undefined,
} }
`); `);
}, },
@ -284,11 +278,11 @@ describe('src/adapter.ts', () => {
expect(response).toMatchInlineSnapshot(` expect(response).toMatchInlineSnapshot(`
{ {
"data": { "data": {
"result": null, "errMsg": undefined,
"errno": undefined,
}, },
"headers": {}, "headers": undefined,
"status": 500, "status": 500,
"statusText": "OK",
} }
`); `);
}, },
@ -302,9 +296,8 @@ describe('src/adapter.ts', () => {
"errMsg": "request:fail", "errMsg": "request:fail",
"errno": 1000, "errno": 1000,
}, },
"headers": {}, "headers": undefined,
"status": 400, "status": undefined,
"statusText": "Fail Adapter",
} }
`); `);
}, },