From a04f833d917cb07c3bd95678260971194179def0 Mon Sep 17 00:00:00 2001 From: zjx0905 <954270063@qq.com> Date: Sat, 12 Aug 2023 22:08:44 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=BA=9F=E5=BC=83=20fork=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BREAKING CHANGE : axios.fork() 已废弃 --- docs/.vitepress/config.ts | 1 - docs/pages/advanced/extend.md | 2 +- docs/pages/advanced/fork.md | 228 ------------------------------ docs/pages/advanced/instance.md | 2 +- docs/pages/advanced/middleware.md | 5 +- src/adpater/createAdapter.ts | 16 +-- src/adpater/getDefaultAdapter.ts | 92 ++++++------ src/core/createInstance.ts | 9 -- src/helpers/ignore.ts | 4 +- test/axios.api.test.ts | 1 - test/axios.instance.test.ts | 1 - test/core/createInstance.test.ts | 1 - test/helpers/ignore.test.ts | 8 +- 13 files changed, 63 insertions(+), 307 deletions(-) delete mode 100644 docs/pages/advanced/fork.md diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 5a3b0a8..d84e2ea 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -123,7 +123,6 @@ function sidebar() { { text: '创建实例', link: '/advanced/instance' }, { text: '扩展实例', link: '/advanced/extend' }, { text: '平台适配器', link: '/advanced/adapter' }, - { text: '派生领域(即将废弃)', link: '/advanced/fork' }, ], collapsed: false, }, diff --git a/docs/pages/advanced/extend.md b/docs/pages/advanced/extend.md index 3f31735..5cf46bd 100644 --- a/docs/pages/advanced/extend.md +++ b/docs/pages/advanced/extend.md @@ -20,7 +20,7 @@ import axios from 'axios-miniprogram'; axios.defaults.baseURL = 'https://api.com'; // 相对地址会进行组合 -// baseURL 最终结果为 https://api.com/uesr +// baseURL 最终结果为 https://api.com/user const instance = axios.extend({ baseURL: 'user', headers: { diff --git a/docs/pages/advanced/fork.md b/docs/pages/advanced/fork.md deleted file mode 100644 index 4d5b10b..0000000 --- a/docs/pages/advanced/fork.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -title: 派生领域 ---- - -# {{ $frontmatter.title }} - -::: tip {{ $frontmatter.title }} -派生新的领域简化 `URL`。 -::: - -::: warning 注意 -该接口即将废弃,请使用功能更强的[扩展实例](./extend)。 -::: - -## 派生领域 - -可以基于 `axios` 派生领域,配置项 `baseURL` 传相对地址时会和 `axios.defaults.baseURL` 一起组合成完整的服务端地址。 - -全局默认配置 `axios.defaults` 和派生领域时传入的配置 `config` 将会按优先级[合并](/basics/defaults#配置合并策略)成领域默认配置 `domain.defaults`。 - -```ts -import axios from 'axios-miniprogram'; - -axios.defaults.baseURL = 'https://api.com'; - -// 相对地址会进行组合 -// baseURL 最终结果为 https://api.com/uesr -const domain = axios.fork({ - baseURL: 'user', - headers: { - common: { - ['Content-Type']: 'application/json', - }, - post: { - ['Content-Type']: 'application/x-www-form-urlencoded', - }, - }, - timeout: 1000, -}); - -// 绝对地址会直接使用 -// baseURL 最终结果为 https://api2.com/user -const domain = axios.fork({ - baseURL: 'https://api2.com/user', - headers: { - common: { - ['Content-Type']: 'application/json', - }, - post: { - ['Content-Type']: 'application/x-www-form-urlencoded', - }, - }, - timeout: 1000, -}); -``` - -## 默认配置 - -可以设置配置项默认值。 - -```ts -import axios from 'axios-miniprogram'; - -axios.defaults.baseURL = 'https://api.com'; - -const domain = axios.fork({ - baseURL: 'user', -}); - -domain.defaults.headers.common['Content-Type'] = 'application/json'; -domain.defaults.timeout = 1000; -``` - -## 拦截器 - -可以使用父级的拦截器,但不支持为领域单独添加拦截器。 - -基于 axios 派生领域。 - -```ts -import axios from 'axios-miniprogram'; - -// 请求拦截器 -axios.interceptors.request.use( - function (config) { - // 在发送请求之前做些什么 - return config; - }, - function (error) { - // 对请求错误做些什么 - return Promise.reject(error); - }, -); - -// 响应拦截器 -axios.interceptors.response.use( - function (response) { - // 在 then 之前做些什么 - return response; - }, - function (error) { - // 在 catch 之前做些什么 - return Promise.reject(error); - }, -); - -const domain = axios.fork({ - baseURL: 'test', -}); - -// 发送请求时会使用 axios 的请求拦截器和响应拦截器 -domain.get('/'); -``` - -基于实例派生领域。 - -```ts -import axios from 'axios-miniprogram'; - -const instance = axios.create({ - baseURL: 'https://api.com', -}); - -// 请求拦截器 -instance.interceptors.request.use( - function (config) { - // 在发送请求之前做些什么 - return config; - }, - function (error) { - // 对请求错误做些什么 - return Promise.reject(error); - }, -); - -// 响应拦截器 -instance.interceptors.response.use( - function (response) { - // 在 then 之前做些什么 - return response; - }, - function (error) { - // 在 catch 之前做些什么 - return Promise.reject(error); - }, -); - -const domain = instance.fork({ - baseURL: 'test', -}); - -// 发送请求时会使用 instance 的请求拦截器和响应拦截器 -domain.get('/'); -``` - -## 使用方式 - -可以使用请求方法发送请求。 - -```ts -import axios from 'axios-miniprogram'; - -axios.defaults.baseURL = 'https://api.com'; - -const domain = axios.fork({ - baseURL: 'user', -}); - -// 请求的服务端地址 https://api.com/uesr/1 -domain - .get('/:id', { - id: 1, - }) - .then((response) => { - // 成功之后做些什么 - }) - .catch((error) => { - // 失败之后做些什么 - }); - -// 请求的服务端地址 https://api.com/uesr -domain - .post('/', { - id: 1, - name: 'user', - }) - .then((response) => { - // 成功之后做些什么 - }) - .catch((error) => { - // 失败之后做些什么 - }); - -// 请求的服务端地址 https://api.com/uesr/1 -domain - .put('/:id', { - name: 'user', - }) - .then((response) => { - // 成功之后做些什么 - }) - .catch((error) => { - // 失败之后做些什么 - }); - -// 请求的服务端地址 https://api.com/uesr/1 -domain - .delete('/:id', { - id: 1, - }) - .then((response) => { - // 成功之后做些什么 - }) - .catch((error) => { - // 失败之后做些什么 - }); -``` - -- [domain.request(url, config?) | domain.request(config)](/basics/request) -- [domain.options(url, config?)](/method/OPTIONS) -- [domain.get(url, params?, config?)](/method/GET) -- [domain.head(url, params?, config?)](/method/HEAD) -- [domain.post(url, data?, config?)](/method/POST) -- [domain.put(url, data?, config?)](/method/PUT) -- [domain.patch(url, data?, config?)](/method/PATCH) -- [domain.delete(url, params?, config?)](/method/DELETE) -- [domain.trace(url, config?)](/method/TRACE) -- [domain.connect(url, config?)](/method/CONNECT) diff --git a/docs/pages/advanced/instance.md b/docs/pages/advanced/instance.md index e105aff..bdc1673 100644 --- a/docs/pages/advanced/instance.md +++ b/docs/pages/advanced/instance.md @@ -99,7 +99,7 @@ const child = instance.extend({ baseURL: 'user', }); -// 请求的服务端地址 https://api2.com/uesr +// 请求的服务端地址 https://api2.com/user child('/'); ``` diff --git a/docs/pages/advanced/middleware.md b/docs/pages/advanced/middleware.md index ad7ad17..8772dc6 100644 --- a/docs/pages/advanced/middleware.md +++ b/docs/pages/advanced/middleware.md @@ -11,9 +11,10 @@ title: 中间件 ## 前言 如果您了解或者使用过[koa](https://github.com/koajs/koa),相信您一定十分了解什么是洋葱模型,中间件该怎么写。 + 中间件是一个异步函数,接收 `context` 和 `next` 两个参数。 -`context` 是一个对象,提供了 `req` 对象和 `res` 对象作为其做成部分。 +`context` 是一个对象,提供了 `req` 对象和 `res` 对象作为其组成部分。 - `context.req`:请求配置。 - `context.res`:请求完成后服务端返回的响应体,它的初始值是 `null`,请求完成之后才能对其进行操作。 @@ -117,6 +118,6 @@ instance.use(async (ctx, next) => { }); // 复用父级中间件 -// axios request -> instance request -> https://api.com/test/uesr -> instance response -> axios response +// axios request -> instance request -> https://api.com/test/user -> instance response -> axios response instance('/user'); ``` diff --git a/src/adpater/createAdapter.ts b/src/adpater/createAdapter.ts index 10e6c50..9afc92b 100644 --- a/src/adpater/createAdapter.ts +++ b/src/adpater/createAdapter.ts @@ -1,6 +1,6 @@ import { isFunction, isPlainObject } from '../helpers/types'; import { assert } from '../helpers/error'; -import { origIgnore } from '../helpers/ignore'; +import { orgIgnore } from '../helpers/ignore'; import { AxiosProgressEvent, AxiosRequestFormData, @@ -281,6 +281,7 @@ export function createAdapter(platform: AxiosAdapterPlatform) { errMsg: responseError.errMsg ?? responseError.errorMessage, errno: responseError.errno ?? responseError.error, }; + transformResponse(responseError); config.fail(responseError); }, @@ -293,7 +294,7 @@ export function createAdapter(platform: AxiosAdapterPlatform) { response.status = response.status ?? response.statusCode; response.headers = response.headers ?? response.header; - origIgnore(response, [ + orgIgnore(response, [ 'statusCode', 'errMsg', 'errno', @@ -324,8 +325,7 @@ export function createAdapter(platform: AxiosAdapterPlatform) { options.fileType = fileType; options.formData = formData; - origIgnore(options, ['params', 'data']); - + orgIgnore(options, ['params', 'data']); return upload(options); } @@ -340,18 +340,16 @@ export function createAdapter(platform: AxiosAdapterPlatform) { response.data = { filePath: response.filePath, tempFilePath: - response.tempFilePath || + response.tempFilePath ?? // response.apFilePath 为支付宝小程序基础库小于 2.7.23 的特有属性。 response.apFilePath, }; - origIgnore(response, ['tempFilePath', 'apFilePath', 'filePath']); - + orgIgnore(response, ['tempFilePath', 'apFilePath', 'filePath']); success(response); }; - origIgnore(options, ['params']); - + orgIgnore(options, ['params']); return download(options); } diff --git a/src/adpater/getDefaultAdapter.ts b/src/adpater/getDefaultAdapter.ts index 63a5f86..2365ea3 100644 --- a/src/adpater/getDefaultAdapter.ts +++ b/src/adpater/getDefaultAdapter.ts @@ -6,52 +6,50 @@ import { AxiosAdapterPlatform, createAdapter } from './createAdapter'; */ export function getDefaultAdapter() { const platform = revisePlatformApiNames(getPlatform()); - if (!isPlatform(platform)) { - return; + if (isPlatform(platform)) { + return createAdapter(platform); } - - function getPlatform() { - const undef = 'undefined'; - - if (typeof wx !== undef) { - return wx; - } else if (typeof my !== undef) { - return my; - } else if (typeof swan !== undef) { - return swan; - } else if (typeof tt !== undef) { - return tt; - } else if (typeof qq !== undef) { - return qq; - } else if (typeof qh !== undef) { - return qh; - } else if (typeof ks !== undef) { - return ks; - } else if (typeof dd !== undef) { - return dd; - } else if (typeof jd !== undef) { - return jd; - } - } - - function revisePlatformApiNames(platform?: AnyObject) { - return ( - platform && { - request: platform.request ?? platform.httpRequest, - upload: platform.upload ?? platform.uploadFile, - download: platform.download ?? platform.downloadFile, - } - ); - } - - function isPlatform(value: any): value is AxiosAdapterPlatform { - return ( - isPlainObject(value) && - isFunction(value.request) && - isFunction(value.upload) && - isFunction(value.download) - ); - } - - return createAdapter(platform); +} + +function getPlatform() { + const undef = 'undefined'; + + if (typeof wx !== undef) { + return wx; + } else if (typeof my !== undef) { + return my; + } else if (typeof swan !== undef) { + return swan; + } else if (typeof tt !== undef) { + return tt; + } else if (typeof qq !== undef) { + return qq; + } else if (typeof qh !== undef) { + return qh; + } else if (typeof ks !== undef) { + return ks; + } else if (typeof dd !== undef) { + return dd; + } else if (typeof jd !== undef) { + return jd; + } +} + +function revisePlatformApiNames(platform?: AnyObject) { + if (platform) { + return { + request: platform.request ?? platform.httpRequest, + upload: platform.upload ?? platform.uploadFile, + download: platform.download ?? platform.downloadFile, + }; + } +} + +function isPlatform(value: any): value is AxiosAdapterPlatform { + return ( + isPlainObject(value) && + isFunction(value.request) && + isFunction(value.upload) && + isFunction(value.download) + ); } diff --git a/src/core/createInstance.ts b/src/core/createInstance.ts index 7a74720..c26f1ca 100644 --- a/src/core/createInstance.ts +++ b/src/core/createInstance.ts @@ -44,14 +44,6 @@ export interface AxiosInstance extends AxiosRequest, Axios { * @param config 默认配置 */ extend(config: AxiosRequestConfig): AxiosInstance; - /** - * 派生领域 - * - * @param config 默认配置 - * - * @deprecated 请使用 extend 替换 fork - */ - fork(config: AxiosRequestConfig): AxiosInstance; } export function createInstance( @@ -72,7 +64,6 @@ export function createInstance( config.baseURL = combineURL(defaults.baseURL, config.baseURL); return createInstance(mergeConfig(defaults, config), context); }; - instance.fork = instance.extend; Object.assign(instance, context); Object.setPrototypeOf(instance, Axios.prototype); diff --git a/src/helpers/ignore.ts b/src/helpers/ignore.ts index 12044ad..f4925f0 100644 --- a/src/helpers/ignore.ts +++ b/src/helpers/ignore.ts @@ -9,7 +9,7 @@ export function ignore( ...keys: K[] ): Omit { const res = { ...obj }; - origIgnore(res, keys); + orgIgnore(res, keys); return res; } @@ -19,7 +19,7 @@ export function ignore( * @param obj 源对象 * @param keys 忽略的键 */ -export function origIgnore(obj: AnyObject, keys: PropertyKey[]) { +export function orgIgnore(obj: AnyObject, keys: PropertyKey[]) { for (const key of keys) { delete obj[key as string | number]; } diff --git a/test/axios.api.test.ts b/test/axios.api.test.ts index 0b4d731..48f522a 100644 --- a/test/axios.api.test.ts +++ b/test/axios.api.test.ts @@ -27,7 +27,6 @@ describe('src/axios.ts', () => { }); expect(instance.interceptors).toBeTypeOf('object'); expect(instance.getUri).toBeTypeOf('function'); - expect(instance.fork).toBeTypeOf('function'); expect(instance.request).toBeTypeOf('function'); eachMethods((k) => { diff --git a/test/axios.instance.test.ts b/test/axios.instance.test.ts index e95bf21..45e2801 100644 --- a/test/axios.instance.test.ts +++ b/test/axios.instance.test.ts @@ -19,7 +19,6 @@ describe('src/axios.ts', () => { expect(axios.create).toBeTypeOf('function'); expect(axios.extend).toBeTypeOf('function'); expect(axios.use).toBeTypeOf('function'); - expect(axios.fork).toBeTypeOf('function'); expect(axios.request).toBeTypeOf('function'); }); diff --git a/test/core/createInstance.test.ts b/test/core/createInstance.test.ts index b29dbbf..c5eab98 100644 --- a/test/core/createInstance.test.ts +++ b/test/core/createInstance.test.ts @@ -12,7 +12,6 @@ describe('src/core/createInstance.ts', () => { expect(i.getUri).toBeTypeOf('function'); expect(i.create).toBeTypeOf('function'); expect(i.extend).toBeTypeOf('function'); - expect(i.fork).toBeTypeOf('function'); expect(i.use).toBeTypeOf('function'); expect(i.request).toBeTypeOf('function'); diff --git a/test/helpers/ignore.test.ts b/test/helpers/ignore.test.ts index 500e98a..5017e8a 100644 --- a/test/helpers/ignore.test.ts +++ b/test/helpers/ignore.test.ts @@ -1,5 +1,5 @@ import { describe, test, expect } from 'vitest'; -import { ignore, origIgnore } from '@/helpers/ignore'; +import { ignore, orgIgnore } from '@/helpers/ignore'; describe('src/helpers/ignore.ts', () => { test('不应该改变传递的对象', () => { @@ -55,20 +55,20 @@ describe('src/helpers/ignore.ts', () => { v3: [], }; - origIgnore(o, ['v1']); + orgIgnore(o, ['v1']); expect(o).toEqual({ v2: {}, v3: [], }); - origIgnore(o, ['v2']); + orgIgnore(o, ['v2']); expect(o).toEqual({ v3: [], }); - origIgnore(o, ['v3']); + orgIgnore(o, ['v3']); expect(o).toEqual({}); });