From b0eaa04c66dc82de944769893f62ecd0c4ae76d8 Mon Sep 17 00:00:00 2001 From: zjx0905 <954270063@qq.com> Date: Mon, 17 Apr 2023 21:31:03 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BB=8E=E5=8F=82=E6=95=B0=E4=B8=AD?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=8A=A8=E6=80=81=E5=9C=B0=E5=9D=80=E5=B1=9E?= =?UTF-8?q?=E6=80=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/pages/advanced/adapter.md | 8 +- docs/pages/advanced/request-interceptor.md | 33 ++++++++ docs/pages/advanced/response-interceptor.md | 33 ++++++++ docs/pages/basics/defaults.md | 2 +- docs/pages/basics/dynamic-url.md | 91 ++++++++++++++++++++- docs/pages/basics/error-handler.md | 39 +++++++++ docs/pages/basics/params-serializer.md | 23 +++++- src/core/transformURL.ts | 2 +- src/helpers/dynamicURL.ts | 14 +++- test/axios.test.ts | 2 +- test/core/Axios.test.ts | 6 +- test/core/dispatchRequest.test.ts | 2 +- test/core/transformURL.test.ts | 2 +- test/helpers/dynamicURL.test.ts | 40 +++++++-- 14 files changed, 274 insertions(+), 23 deletions(-) diff --git a/docs/pages/advanced/adapter.md b/docs/pages/advanced/adapter.md index d0a7aff..721bf56 100644 --- a/docs/pages/advanced/adapter.md +++ b/docs/pages/advanced/adapter.md @@ -140,7 +140,7 @@ axios.defaults.adapter = (config) => { fail: (error) => { config.fail({ // 状态码 - status: '400', + status: 400, // 状态文本 statusText: 'Fail Adapter', @@ -185,7 +185,7 @@ axios.defaults.adapter = (config) => { fail: (error) => { config.fail({ // 状态码 - status: '400', + status: 400, // 状态文本 statusText: 'Fail Adapter', @@ -226,7 +226,7 @@ axios.defaults.adapter = (config) => { fail: (error) => { config.fail({ // 状态码 - status: '400', + status: 400, // 状态文本 statusText: 'Fail Adapter', @@ -259,7 +259,7 @@ axios.defaults.adapter = axios.createAdapter({ }); ``` -可以进一步抹平存在差异的部分,实现完美适配全平台。 +也可以进一步抹平存在差异的部分,实现完美适配全平台。 ```ts import axios from 'axios-miniprogram'; diff --git a/docs/pages/advanced/request-interceptor.md b/docs/pages/advanced/request-interceptor.md index 28abf8c..4d9a3a1 100644 --- a/docs/pages/advanced/request-interceptor.md +++ b/docs/pages/advanced/request-interceptor.md @@ -80,3 +80,36 @@ const ejectId = axios.interceptors.request.use( // 移除请求拦截器 axios.interceptors.request.eject(ejectId); ``` + +## 移除所有请求拦截器 + +可以移除所有请求拦截器。 + +```ts +import axios from 'axios-miniprogram'; + +axios.interceptors.request.use( + function (config) { + // 在发送请求之前做些什么 + return config; + }, + function (error) { + // 对请求错误做些什么 + return Promise.reject(error); + }, +); + +axios.interceptors.request.use( + function (config) { + // 在发送请求之前做些什么 + return config; + }, + function (error) { + // 对请求错误做些什么 + return Promise.reject(error); + }, +); + +// 移除所有请求拦截器 +axios.interceptors.request.clear(); +``` diff --git a/docs/pages/advanced/response-interceptor.md b/docs/pages/advanced/response-interceptor.md index acea047..c097d3a 100644 --- a/docs/pages/advanced/response-interceptor.md +++ b/docs/pages/advanced/response-interceptor.md @@ -80,3 +80,36 @@ const ejectId = axios.interceptors.response.use( // 移除响应拦截器 axios.interceptors.response.eject(ejectId); ``` + +## 移除所有响应拦截器 + +可以移除所有响应拦截器。 + +```ts +import axios from 'axios-miniprogram'; + +axios.interceptors.request.use( + function (response) { + // 在 then 之前做些什么 + return response; + }, + function (error) { + // 在 catch 之前做些什么 + return Promise.reject(error); + }, +); + +axios.interceptors.request.use( + function (response) { + // 在 then 之前做些什么 + return response; + }, + function (error) { + // 在 catch 之前做些什么 + return Promise.reject(error); + }, +); + +// 移除所有响应拦截器 +axios.interceptors.request.clear(); +``` diff --git a/docs/pages/basics/defaults.md b/docs/pages/basics/defaults.md index 0ff870e..a0ad4a4 100644 --- a/docs/pages/basics/defaults.md +++ b/docs/pages/basics/defaults.md @@ -57,7 +57,7 @@ title: 默认配置 可以给属性设置默认值。 -部分示例: +列举部分示例: ```ts import axios from 'axios-miniprogram'; diff --git a/docs/pages/basics/dynamic-url.md b/docs/pages/basics/dynamic-url.md index 79f9daf..1f07f8f 100644 --- a/docs/pages/basics/dynamic-url.md +++ b/docs/pages/basics/dynamic-url.md @@ -8,4 +8,93 @@ title: 动态地址 简化设置地址参数。 ::: -未完待续... +## 设置 `params` 动态参数 + +可以设置属性 `params`,最终会从 `params` 中获取到对应的值。 + +::: warning 注意 +获取到值之后,会从 `params` 中删除对应的属性。 +::: + +```ts +import axios from 'axios-miniprogram'; + +// 请求的服务端地址 https://api.com/1 +// 获取到 id 之后,会从 params 中删除 id +axios('https://api.com/:id', { + params: { + id: 1, + }, +}) + .then((response) => { + // 成功之后做些什么 + }) + .catch((error) => { + // 失败之后做些什么 + }); +``` + +## 设置 `data` 动态参数 + +可以设置属性 `data`,最终会从 `data` 中获取到对应的值。 + +```ts +import axios from 'axios-miniprogram'; + +// 请求的服务端地址 https://api.com/1 +// 获取到 id 之后,不会从 data 中删除 id +axios('https://api.com/:id', { + method: 'POST', + data: { + id: 1, + }, +}) + .then((response) => { + // 成功之后做些什么 + }) + .catch((error) => { + // 失败之后做些什么 + }); +``` + +## 同时设置 `params` 和 `data` + +可以同时设置 `params` 和 `data`,会优先从 `params` 中获取对应的值。 + +```ts +import axios from 'axios-miniprogram'; + +// 请求的服务端地址 https://api.com/1 +axios('https://api.com/:id', { + method: 'POST', + params: { + id: 1, + }, + data: { + id: 2, + }, +}) + .then((response) => { + // 成功之后做些什么 + }) + .catch((error) => { + // 失败之后做些什么 + }); + +// 请求的服务端地址 https://api.com/1/2 +axios('https://api.com/:id1/:id2', { + method: 'POST', + params: { + id1: 1, + }, + data: { + id2: 2, + }, +}) + .then((response) => { + // 成功之后做些什么 + }) + .catch((error) => { + // 失败之后做些什么 + }); +``` diff --git a/docs/pages/basics/error-handler.md b/docs/pages/basics/error-handler.md index 83ff417..2142b82 100644 --- a/docs/pages/basics/error-handler.md +++ b/docs/pages/basics/error-handler.md @@ -116,3 +116,42 @@ axios('https://api.com/test', { // 失败之后做些什么 }); ``` + +## 全局错误处理 + +可以把 `errorHandler` 设置到默认配置中,每一个请求都可以进行错误处理。 + +```ts +import axios from 'axios-miniprogram'; + +// 全局错误处理 +axios.defaults.errorHandler = (error) => { + if (axios.isAxiosError(error)) { + // 响应错误 + + const { + // 错误消息 + message, + + // 请求配置 + config, + + // 请求任务,也就是请求函数返回的结果 + request, + + // 响应体 + response, + } = error; + + if (response.isFail) { + // 平台或适配器错误 + } else { + // 使用 `validateStatus` 自定义抛出的错误 + } + } else if (axios.isCancel(error)) { + // 取消请求 + } else { + // 其他错误 + } +}; +``` diff --git a/docs/pages/basics/params-serializer.md b/docs/pages/basics/params-serializer.md index e4ffa85..85e6b17 100644 --- a/docs/pages/basics/params-serializer.md +++ b/docs/pages/basics/params-serializer.md @@ -8,4 +8,25 @@ title: 参数系列化 支持自定义参数系列化器。 ::: -未完待续... +## 自定义参数系列化器 + +可以用自己的方式对参数进行系列化。 + +```ts +import axios from 'axios-miniprogram'; + +axios('https://api.com', { + params: { + id: 1, + }, + paramsSerializer(params) { + return qs.stringify(params); + }, +}) + .then((response) => { + // 请求成功后做些什么 + }) + .catch((error) => { + // 请求失败后做些什么 + }); +``` diff --git a/src/core/transformURL.ts b/src/core/transformURL.ts index 1c77b9a..a28c7f3 100644 --- a/src/core/transformURL.ts +++ b/src/core/transformURL.ts @@ -8,7 +8,7 @@ export function transformURL(config: AxiosRequestConfig) { let url = config.url ?? ''; if (!isAbsoluteURL(url)) url = combineURL(config.baseURL ?? '', url); - url = dynamicURL(url, Object.assign({}, config.params, config.data)); + url = dynamicURL(url, config.params, config.data); url = buildURL(url, config.params, config.paramsSerializer); return url; diff --git a/src/helpers/dynamicURL.ts b/src/helpers/dynamicURL.ts index b98b6c8..ecbe70b 100644 --- a/src/helpers/dynamicURL.ts +++ b/src/helpers/dynamicURL.ts @@ -1,4 +1,14 @@ const dynamicRE = /\/:([^/]+)/g; -export function dynamicURL(url: string, data: AnyObject) { - return url.replace(dynamicRE, (_, $2) => `/${data[$2]}`); +export function dynamicURL( + url: string, + params: AnyObject = {}, + data: AnyObject = {}, +) { + return url.replace(dynamicRE, (_, $2) => { + const value = params[$2] ?? data[$2]; + if ($2 in params) { + delete params[$2]; + } + return `/${value}`; + }); } diff --git a/test/axios.test.ts b/test/axios.test.ts index 2e7e611..78eb9c3 100644 --- a/test/axios.test.ts +++ b/test/axios.test.ts @@ -9,7 +9,7 @@ describe('src/axios.ts', () => { headers: { type: 'json' }, data: { v1: 1 }, before: (config) => { - expect(config.url).toBe('http://api.com/test/1?id=1'); + expect(config.url).toBe('http://api.com/test/1'); }, }), baseURL: 'http://api.com', diff --git a/test/core/Axios.test.ts b/test/core/Axios.test.ts index dfe2896..14468f0 100644 --- a/test/core/Axios.test.ts +++ b/test/core/Axios.test.ts @@ -68,8 +68,8 @@ describe('src/core/Axios.ts', () => { const c2 = { adapter: mockAdapter({ before: (config) => { - expect(config.url).toBe('http://api.com/test/1?id=1'); - expect(config.params).toEqual(p); + expect(config.url).toBe('http://api.com/test/1'); + expect(config.params).toEqual({}); }, data, }), @@ -79,7 +79,7 @@ describe('src/core/Axios.ts', () => { axios[a]('test', p, c1).then((res) => { expect(res.data).toEqual(data); }); - axios[a]('test/:id', p, c2).then((res) => { + axios[a]('test/:id', { ...p }, c2).then((res) => { expect(res.data).toEqual(data); }); }); diff --git a/test/core/dispatchRequest.test.ts b/test/core/dispatchRequest.test.ts index 499c947..8205455 100644 --- a/test/core/dispatchRequest.test.ts +++ b/test/core/dispatchRequest.test.ts @@ -99,7 +99,7 @@ describe('src/core/dispatchRequest.ts', () => { dispatchRequest(c3); expect(c1.url).toBe('http://api.com/test'); - expect(c2.url).toBe('http://api.com/test/1?id=1'); + expect(c2.url).toBe('http://api.com/test/1'); expect(c3.url).toBe('http://api.com/test/1'); }); diff --git a/test/core/transformURL.test.ts b/test/core/transformURL.test.ts index b22b311..5e09208 100644 --- a/test/core/transformURL.test.ts +++ b/test/core/transformURL.test.ts @@ -42,7 +42,7 @@ describe('src/core/transformURL.ts', () => { type: 0, }, }), - ).toBe('http://api.com/test/axios/0?name=axios&type=0'); + ).toBe('http://api.com/test/axios/0'); expect( transformURL({ baseURL: 'http://api.com', diff --git a/test/helpers/dynamicURL.test.ts b/test/helpers/dynamicURL.test.ts index 85ee4d6..2e82950 100644 --- a/test/helpers/dynamicURL.test.ts +++ b/test/helpers/dynamicURL.test.ts @@ -2,22 +2,48 @@ import { describe, test, expect } from 'vitest'; import { dynamicURL } from '@/helpers/dynamicURL'; describe('src/helpers/dynamicURL.ts', () => { - test('应该替换关键字', () => { + test('应该支持空参数', () => { + expect(dynamicURL('http://api.com/test/:id')).toBe( + 'http://api.com/test/undefined', + ); expect(dynamicURL('http://api.com/test/:id', {})).toBe( 'http://api.com/test/undefined', ); + expect(dynamicURL('http://api.com/test/:id', undefined, {})).toBe( + 'http://api.com/test/undefined', + ); + }); + + test('应该支持 params', () => { expect(dynamicURL('http://api.com/test/:id', { id: 1 })).toBe( 'http://api.com/test/1', ); }); - test('应该支持多个关键字', () => { + test('应该支持 data', () => { + expect(dynamicURL('http://api.com/test/:id', {}, { id: 1 })).toBe( + 'http://api.com/test/1', + ); + }); + + test('应该优先从 params 取值', () => { + expect(dynamicURL('http://api.com/test/:id', { id: 1 }, { id: 2 })).toBe( + 'http://api.com/test/1', + ); expect( - dynamicURL('http://api.com/tests/name/:name/type/:type/list', { - name: 'axios', - type: 0, - }), - ).toBe('http://api.com/tests/name/axios/type/0/list'); + dynamicURL('http://api.com/test/:id1/:id2', { id1: 1 }, { id2: 2 }), + ).toBe('http://api.com/test/1/2'); + }); + + test('应该从 params 删除对应的值', () => { + const p = { id1: 1 }; + const d = { id2: 2 }; + + expect(dynamicURL('http://api.com/test/:id1/:id2', p, d)).toBe( + 'http://api.com/test/1/2', + ); + expect(p.id1).toBeUndefined(); + expect(d.id2).toBe(2); }); test('应该忽略端口号', () => {