From f23d27024fd53d15ba4fa60a3f99748349cda5d4 Mon Sep 17 00:00:00 2001 From: zjx0905 <954270063@qq.com> Date: Thu, 27 Apr 2023 21:25:47 +0800 Subject: [PATCH] =?UTF-8?q?chore:=20=E4=B8=80=E4=BA=9B=E5=B0=8F=E7=9A=84?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/adpater/createAdapter.ts | 20 ++++----- src/core/Axios.ts | 13 +++++- src/core/createInstance.ts | 12 +++--- src/core/mergeConfig.ts | 5 +++ src/helpers/ignore.ts | 24 +++++++++-- test/adpater/createAdapter.test.ts | 69 ++++++++++++++++-------------- test/helpers/ignore.test.ts | 38 +++++++++++++++- 7 files changed, 128 insertions(+), 53 deletions(-) diff --git a/src/adpater/createAdapter.ts b/src/adpater/createAdapter.ts index 9bddaec..ccdf4af 100644 --- a/src/adpater/createAdapter.ts +++ b/src/adpater/createAdapter.ts @@ -1,5 +1,6 @@ import { isFunction, isPlainObject } from '../helpers/isTypes'; import { assert } from '../helpers/error'; +import { origIgnore } from '../helpers/ignore'; import { AxiosProgressEvent, AxiosRequestFormData, @@ -291,7 +292,8 @@ export function createAdapter(platform: AxiosAdapterPlatform) { ) { response.status = response.status ?? response.statusCode; response.headers = response.headers ?? response.header; - clean(response, ['statusCode', 'errMsg', 'errno', 'header']); + + origIgnore(response, ['statusCode', 'errMsg', 'errno', 'header']); } function processRequest( @@ -307,13 +309,14 @@ export function createAdapter(platform: AxiosAdapterPlatform) { ): AxiosAdapterPlatformTask { 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; + origIgnore(options, ['params', 'data']); + return upload(options); } @@ -323,7 +326,6 @@ export function createAdapter(platform: AxiosAdapterPlatform) { ): AxiosAdapterPlatformTask { const options = baseOptions as AxiosAdapterDownloadOptions; const { params, success } = options; - options.filePath = params?.filePath; options.success = (response) => { response.data = { @@ -333,18 +335,16 @@ export function createAdapter(platform: AxiosAdapterPlatform) { // response.apFilePath 为支付宝小程序基础库小于 2.7.23 的特有属性。 response.apFilePath, }; - clean(response, ['tempFilePath', 'apFilePath', 'filePath']); + + origIgnore(response, ['tempFilePath', 'apFilePath', 'filePath']); + success(response); }; + origIgnore(options, ['params']); + return download(options); } - function clean(obj: AnyObject, keys: string[]) { - for (const key of keys) { - delete obj[key]; - } - } - return adapter; } diff --git a/src/core/Axios.ts b/src/core/Axios.ts index 16f7a7a..2ab521e 100644 --- a/src/core/Axios.ts +++ b/src/core/Axios.ts @@ -353,7 +353,11 @@ export interface AxiosConstructor { } export default class Axios { + /** + * 父级实例 + */ #parent?: Axios; + /** * 默认请求配置 */ @@ -430,8 +434,13 @@ export default class Axios { */ use: (middleware: MiddlewareCallback) => MiddlewareManager; - constructor(defaults: AxiosRequestConfig, parent?: Axios) { - this.defaults = defaults; + /** + * + * @param config 默认配置 + * @param parent 父级实例 + */ + constructor(config: AxiosRequestConfig, parent?: Axios) { + this.defaults = config; this.#parent = parent; this.use = this.#middleware.use; } diff --git a/src/core/createInstance.ts b/src/core/createInstance.ts index 2218d9a..22194f7 100644 --- a/src/core/createInstance.ts +++ b/src/core/createInstance.ts @@ -53,19 +53,19 @@ export interface AxiosInstance extends AxiosRequest, Axios { fork(config: AxiosRequestConfig): AxiosInstance; } -export function createInstance(config: AxiosRequestConfig, parent?: Axios) { - const context = new Axios(config, parent); +export function createInstance(defaults: AxiosRequestConfig, parent?: Axios) { + const context = new Axios(defaults, parent); const instance = context.request as AxiosInstance; instance.getUri = function getUri(config) { - return transformURL(mergeConfig(instance.defaults, config)); + return transformURL(mergeConfig(defaults, config)); }; instance.create = function create(config) { - return createInstance(mergeConfig(instance.defaults, config)); + return createInstance(mergeConfig(defaults, config)); }; instance.extend = function extend(config) { - config.baseURL = combineURL(instance.defaults.baseURL, config.baseURL); - return createInstance(mergeConfig(instance.defaults, config), context); + config.baseURL = combineURL(defaults.baseURL, config.baseURL); + return createInstance(mergeConfig(defaults, config), context); }; instance.fork = instance.extend; diff --git a/src/core/mergeConfig.ts b/src/core/mergeConfig.ts index ef41b00..6456daa 100644 --- a/src/core/mergeConfig.ts +++ b/src/core/mergeConfig.ts @@ -13,6 +13,11 @@ const deepMergeConfigMap: Record = { params: true, }; +/** + * 合并配置 + * + * 按照设定的优先级进行合并 + */ export function mergeConfig( config1: AxiosRequestConfig = {}, config2: AxiosRequestConfig = {}, diff --git a/src/helpers/ignore.ts b/src/helpers/ignore.ts index af4437c..12044ad 100644 --- a/src/helpers/ignore.ts +++ b/src/helpers/ignore.ts @@ -1,8 +1,26 @@ +/** + * 忽略键值对 + * + * @param obj 源对象 + * @param keys 忽略的键 + */ export function ignore( obj: T, ...keys: K[] ): Omit { - const result = { ...obj }; - for (const key of keys) delete result[key]; - return result; + const res = { ...obj }; + origIgnore(res, keys); + return res; +} + +/** + * 从源对象删除键值对 + * + * @param obj 源对象 + * @param keys 忽略的键 + */ +export function origIgnore(obj: AnyObject, keys: PropertyKey[]) { + for (const key of keys) { + delete obj[key as string | number]; + } } diff --git a/test/adpater/createAdapter.test.ts b/test/adpater/createAdapter.test.ts index 73563c9..a23ded2 100644 --- a/test/adpater/createAdapter.test.ts +++ b/test/adpater/createAdapter.test.ts @@ -56,6 +56,7 @@ describe('src/adapter/createAdapter.ts', () => { data: { name: 'file', filePath: '/path/file', + fileType: 'image', user: 'test', id: 1, }, @@ -78,7 +79,8 @@ describe('src/adapter/createAdapter.ts', () => { expect(p.request).not.toBeCalled(); a(r); - expect(p.request.mock.calls[0][0]).toMatchInlineSnapshot(` + const rOpts = p.request.mock.calls[0][0]; + expect(rOpts).toMatchInlineSnapshot(` { "fail": [Function], "header": { @@ -93,21 +95,39 @@ describe('src/adapter/createAdapter.ts', () => { "url": "test", } `); + expect(rOpts.header).toEqual(r.headers); + + expect(p.download).not.toBeCalled(); + a(d); + const dOpts = p.download.mock.calls[0][0]; + expect(dOpts).toMatchInlineSnapshot(` + { + "fail": [Function], + "filePath": "/path/file", + "header": { + "Accept": "application/json, text/plain, */*", + }, + "headers": { + "Accept": "application/json, text/plain, */*", + }, + "method": "GET", + "success": [Function], + "type": "download", + "url": "test", + } + `); + expect(dOpts.header).toEqual(d.headers); + expect(dOpts.filePath).toEqual(d.params.filePath); expect(p.upload).not.toBeCalled(); a(u); - expect(p.upload.mock.calls[0][0]).toMatchInlineSnapshot(` + const uOpts = p.upload.mock.calls[0][0]; + expect(uOpts).toMatchInlineSnapshot(` { - "data": { - "filePath": "/path/file", - "id": 1, - "name": "file", - "user": "test", - }, "fail": [Function], "fileName": "file", "filePath": "/path/file", - "fileType": undefined, + "fileType": "image", "formData": { "id": 1, "user": "test", @@ -125,28 +145,15 @@ describe('src/adapter/createAdapter.ts', () => { "url": "test", } `); - - expect(p.download).not.toBeCalled(); - a(d); - expect(p.download.mock.calls[0][0]).toMatchInlineSnapshot(` - { - "fail": [Function], - "filePath": "/path/file", - "header": { - "Accept": "application/json, text/plain, */*", - }, - "headers": { - "Accept": "application/json, text/plain, */*", - }, - "method": "GET", - "params": { - "filePath": "/path/file", - }, - "success": [Function], - "type": "download", - "url": "test", - } - `); + expect(uOpts.header).toEqual(u.headers); + expect(uOpts.name).toEqual(u.data.name); + expect(uOpts.fileName).toEqual(u.data.name); + expect(uOpts.filePath).toEqual(u.data.filePath); + expect(uOpts.fileType).toEqual(u.data.fileType); + expect(uOpts.formData).toEqual({ + id: u.data.id, + user: u.data.user, + }); }); test('应该支持转换下载数据', () => { diff --git a/test/helpers/ignore.test.ts b/test/helpers/ignore.test.ts index 2a0c3f2..500e98a 100644 --- a/test/helpers/ignore.test.ts +++ b/test/helpers/ignore.test.ts @@ -1,11 +1,22 @@ import { describe, test, expect } from 'vitest'; -import { ignore } from '@/helpers/ignore'; +import { ignore, origIgnore } from '@/helpers/ignore'; describe('src/helpers/ignore.ts', () => { test('不应该改变传递的对象', () => { expect(ignore({ v1: 1 })).toEqual({ v1: 1 }); }); + test('应该不改变源对象', () => { + const o = { + v1: 1, + }; + + expect(ignore(o, 'v1')).toEqual({}); + expect(o).toEqual({ + v1: 1, + }); + }); + test('应该忽略指定键值', () => { const o = { v1: 1, @@ -36,4 +47,29 @@ describe('src/helpers/ignore.ts', () => { }); expect(ignore(o, 'v1', 'v2', 'v3')).toEqual({}); }); + + test('应该从源对象删除', () => { + const o = { + v1: 1, + v2: {}, + v3: [], + }; + + origIgnore(o, ['v1']); + + expect(o).toEqual({ + v2: {}, + v3: [], + }); + + origIgnore(o, ['v2']); + + expect(o).toEqual({ + v3: [], + }); + + origIgnore(o, ['v3']); + + expect(o).toEqual({}); + }); });