From 1867273460de404cf3ece76ecb0b69f95ff7f5a0 Mon Sep 17 00:00:00 2001 From: zjx0905 <954270063@qq.com> Date: Thu, 20 Apr 2023 13:56:17 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=BB=98=E8=AE=A4=E5=80=BC?= =?UTF-8?q?=E7=9A=84=E8=AE=BE=E7=BD=AE=E6=B5=81=E7=A8=8B=E7=A7=BB=E5=88=B0?= =?UTF-8?q?=20request=20=E9=87=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/pages/advanced/adapter.md | 54 +++++++---- package.json | 2 +- src/adapter.ts | 168 ++++++++++++++++----------------- src/core/Axios.ts | 4 +- src/core/request.ts | 7 +- test/adapter.test.ts | 29 +++--- 6 files changed, 133 insertions(+), 131 deletions(-) diff --git a/docs/pages/advanced/adapter.md b/docs/pages/advanced/adapter.md index c0111ff..9d09f56 100644 --- a/docs/pages/advanced/adapter.md +++ b/docs/pages/advanced/adapter.md @@ -91,7 +91,7 @@ import axios from 'axios-miniprogram'; // 适配器 axios.defaults.adapter = (config) => { - // 可以先看看 config 都有哪些东西 + // 可以先看看 config 上都有哪些属性 console.log(config); // 开始适配不同类型的请求 @@ -122,13 +122,16 @@ axios.defaults.adapter = (config) => { success: (response) => { config.success({ // 状态码 + // 默认值:200 status: response.statusCode, - // 状态文本,选填,不传默认 'OK' + // 状态文本 + // 默认值:'OK' statusText: 'OK', // 响应头 - headers: response.header ?? {}, + // 默认值:{} + headers: response.header, // 响应数据 data: response.data, @@ -139,13 +142,16 @@ axios.defaults.adapter = (config) => { }, fail: (error) => { config.fail({ - // 状态码,选填,不传默认 400 + // 状态码 + // 默认值:400 status: 400, - // 状态文本,选填,不传默认 'Fail Adapter' - statusText: 'Fail Adapter', + // 状态文本 + // 默认值:'Fail' + statusText: 'Fail', - // 响应头,选填,不传默认 {} + // 响应头 + // 默认值:{} headers: {}, // 响应数据 @@ -171,12 +177,15 @@ axios.defaults.adapter = (config) => { success: (response) => { config.success({ // 状态码 + // 默认值:200 status: response.statusCode, - // 状态文本,选填,不传默认 'OK' + // 状态文本 + // 默认值:'OK' statusText: 'OK', // 响应头 + // 默认值:{} headers: response.header, // 响应数据 @@ -185,13 +194,16 @@ axios.defaults.adapter = (config) => { }, fail: (error) => { config.fail({ - // 状态码,选填,不传默认 400 + // 状态码 + // 默认值:400 status: 400, - // 状态文本,选填,不传默认 'Fail Adapter' - statusText: 'Fail Adapter', + // 状态文本 + // 默认值:'Fail' + statusText: 'Fail', - // 响应头,选填,不传默认 {} + // 响应头 + // 默认值:{} headers: {}, // 响应数据 @@ -210,13 +222,16 @@ axios.defaults.adapter = (config) => { success: (response) => { config.success({ // 状态码 + // 默认值:200 status: response.statusCode, - // 状态文本,选填,不传默认 'OK' + // 状态文本 + // 默认值:'OK' statusText: 'OK', // 响应头 - headers: response.header ?? {}, + // 默认值:{} + headers: response.header, // 响应数据 data: { @@ -227,13 +242,16 @@ axios.defaults.adapter = (config) => { }, fail: (error) => { config.fail({ - // 状态码,选填,不传默认 400 + // 状态码 + // 默认值:400 status: 400, - // 状态文本,选填,不传默认 'Fail Adapter' - statusText: 'Fail Adapter', + // 状态文本 + // 默认值:'Fail' + statusText: 'Fail', - // 响应头,选填,不传默认 {} + // 响应头 + // 默认值:{} headers: {}, // 响应数据 diff --git a/package.json b/package.json index f7c4cf2..0f24f39 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "main": "dist/axios-miniprogram.cjs.js", "module": "dist/axios-miniprogram.esm.js", "types": "dist/axios-miniprogram.d.ts", - "type": "module", "files": [ "dist" ], @@ -25,6 +24,7 @@ }, "homepage": "https://axios-miniprogram.com", "license": "MIT", + "type": "module", "scripts": { "cz": "simple-git-hooks && czg", "build": "esno scripts/build.ts", diff --git a/src/adapter.ts b/src/adapter.ts index 696271f..b654666 100644 --- a/src/adapter.ts +++ b/src/adapter.ts @@ -1,9 +1,4 @@ -import { - isFunction, - isPlainObject, - isString, - isUndefined, -} from './helpers/isTypes'; +import { isFunction, isPlainObject } from './helpers/isTypes'; import { assert } from './helpers/error'; import { AxiosProgressCallback, @@ -138,8 +133,17 @@ export interface AxiosAdapterRequestConfig extends AnyObject { * 请求函数基本选项 */ export interface AxiosAdapterBaseOptions extends AxiosAdapterRequestConfig { + /** + * 请求头,同 headers + */ header?: AxiosRequestHeaders; + /** + * 成功的回调 + */ success(response: AxiosAdapterResponse): void; + /** + * 失败的回调 + */ fail(error: AxiosAdapterResponseError): void; } @@ -152,6 +156,9 @@ export type AxiosAdapterRequestOptions = AxiosAdapterBaseOptions; * 下载函数选项 */ export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions { + /** + * 文件下载后存储的路径 + */ filePath?: string; } @@ -161,7 +168,17 @@ export interface AxiosAdapterDownloadOptions extends AxiosAdapterBaseOptions { export interface AxiosAdapterUploadOptions extends AxiosAdapterBaseOptions, AxiosRequestFormData { + /** + * [钉钉小程序用 fileName 代替 name](https://open.dingtalk.com/document/orgapp/dd-upload-objects#title-ngk-rr1-eow) + */ fileName: string; + /** + * 钉钉小程序|支付宝小程序特有参数 + */ + fileType?: 'image' | 'video' | 'audie'; + /** + * 额外的数据 + */ formData?: AnyObject; } @@ -290,15 +307,42 @@ export function createAdapter(platform: AxiosAdapterPlatform) { function adapter( config: AxiosAdapterRequestConfig, ): AxiosAdapterPlatformTask { - const baseOptions = transformOptions(config); - + const options = transformOptions(config); switch (config.type) { case 'request': - return processRequest(platform.request, baseOptions); + return processRequest(platform.request, options); case 'download': - return processDownload(platform.download, baseOptions); + return processDownload(platform.download, options); 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, baseOptions: AxiosAdapterBaseOptions, ): AxiosAdapterPlatformTask { - const { name, filePath, fileType, ...formData } = - baseOptions.data as AxiosRequestFormData; - const options = { - ...baseOptions, - name, - /** - * [钉钉小程序用 fileName 代替 name](https://open.dingtalk.com/document/orgapp/dd-upload-objects#title-ngk-rr1-eow) - */ - fileName: name, - filePath, - /** - * 钉钉小程序|支付宝小程序特有参数 - */ - fileType, - formData, - }; + const options = baseOptions as AxiosAdapterUploadOptions; + const { name, filePath, fileType, ...formData } = options.data as AnyObject; + + options.name = name; + options.fileName = name; + options.filePath = filePath; + options.fileType = fileType; + options.formData = formData; return upload(options); } @@ -337,74 +373,28 @@ export function createAdapter(platform: AxiosAdapterPlatform) { download: AxiosAdapterDownload, baseOptions: AxiosAdapterBaseOptions, ): AxiosAdapterPlatformTask { - const options: AxiosAdapterDownloadOptions = { - ...baseOptions, - filePath: baseOptions.params?.filePath, - success(response): void { - injectDownloadData(response); - baseOptions.success(response); - }, + const options = baseOptions as AxiosAdapterDownloadOptions; + const { params, success } = options; + + options.filePath = params?.filePath; + options.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); } - function transformResponse(response: AnyObject): void { - 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[]) { + function clean(obj: AnyObject, keys: string[]) { for (const key of keys) { - delete response[key]; + delete obj[key]; } } diff --git a/src/core/Axios.ts b/src/core/Axios.ts index cf3c2dc..6b1b99a 100644 --- a/src/core/Axios.ts +++ b/src/core/Axios.ts @@ -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; /** * 失败的请求,指没能够成功响应的请求 */ diff --git a/src/core/request.ts b/src/core/request.ts index 9a79a02..eb1a491 100644 --- a/src/core/request.ts +++ b/src/core/request.ts @@ -56,10 +56,11 @@ export function request(config: AxiosRequestConfig) { response.config = config; response.request = adapterTask; - if (config.validateStatus?.(response.status) ?? true) { + const { validateStatus } = config; + if (!isFunction(validateStatus) || validateStatus(response.status)) { resolve(response); } 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; responseError.isFail = true; responseError.status = responseError.status ?? 400; - responseError.statusText = responseError.statusText ?? 'Fail Adapter'; + responseError.statusText = responseError.statusText ?? 'Fail'; responseError.headers = responseError.headers ?? {}; responseError.config = config; responseError.request = adapterTask; diff --git a/test/adapter.test.ts b/test/adapter.test.ts index 08e570a..d789360 100644 --- a/test/adapter.test.ts +++ b/test/adapter.test.ts @@ -81,9 +81,6 @@ describe('src/adapter.ts', () => { expect(p.request.mock.calls[0][0]).toMatchInlineSnapshot(` { "fail": [Function], - "header": { - "Accept": "application/json, text/plain, */*", - }, "headers": { "Accept": "application/json, text/plain, */*", }, @@ -112,9 +109,6 @@ describe('src/adapter.ts', () => { "id": 1, "user": "test", }, - "header": { - "Accept": "application/json, text/plain, */*", - }, "headers": { "Accept": "application/json, text/plain, */*", }, @@ -132,9 +126,6 @@ describe('src/adapter.ts', () => { { "fail": [Function], "filePath": "/path/file", - "header": { - "Accept": "application/json, text/plain, */*", - }, "headers": { "Accept": "application/json, text/plain, */*", }, @@ -271,9 +262,12 @@ describe('src/adapter.ts', () => { fail: (response: any) => { expect(response).toMatchInlineSnapshot(` { - "headers": {}, - "status": 400, - "statusText": "Fail Adapter", + "data": { + "errMsg": undefined, + "errno": undefined, + }, + "headers": undefined, + "status": undefined, } `); }, @@ -284,11 +278,11 @@ describe('src/adapter.ts', () => { expect(response).toMatchInlineSnapshot(` { "data": { - "result": null, + "errMsg": undefined, + "errno": undefined, }, - "headers": {}, + "headers": undefined, "status": 500, - "statusText": "OK", } `); }, @@ -302,9 +296,8 @@ describe('src/adapter.ts', () => { "errMsg": "request:fail", "errno": 1000, }, - "headers": {}, - "status": 400, - "statusText": "Fail Adapter", + "headers": undefined, + "status": undefined, } `); },